【问题标题】:Why I must declare type parameter before return type in Java?为什么我必须在 Java 中的返回类型之前声明类型参数?
【发布时间】:2020-11-11 18:33:21
【问题描述】:

没有对泛型的任何介绍,我将立即发布我的问题。为什么这是正确的:

static<T extends Object> void m1(List<T> list){
        //some code
    }

这不是(不编译):

static void m2 (List<T extends Object> list){
        //some code
    }

请记住,我们可以在相同的方法中使用 通配符,这样编译得很好:

static void m2 (List<? extends Object> list){
        //some code
    }

总结一下,为什么我们可以在参数中使用通配符声明,而使用类型参数却必须在返回类型之前声明呢?

【问题讨论】:

  • 假设您想定义一个类型并从同一方法返回该类型的对象。签名将是static T &lt;T extends Object&gt; m1(List&lt;T&gt; list),但这没有意义,因为T 将在定义之前使用。
  • 因为编译器知道? 是什么意思,但它不知道T 是什么意思。你必须声明T,就像你需要声明任何变量或方法一样。首先你必须声明它,然后你才能使用它。
  • 如果你把List&lt;T&gt;作为一个参数,没有迹象表明T是一个泛型类型参数而不是一个具体类型。
  • &lt;? extends Object&gt; 不会尝试定义 T 或任何其他标识符。它只是告诉编译器“这个列表有一个特定的类型,但我不知道它是什么。”
  • @Markus 将? 视为null。你不需要声明它,但T 你需要。另请注意,您可以对T 使用任何内容。你也可以写SomeType。在签名中使用&lt;...&gt; 就是您为通用方法声明这样一个通用参数的方式。

标签: java generics wildcard type-parameter


【解决方案1】:

主要有两点。

首先,正如@akuzminykh 在 cmets 中对问题所说,? 通配符基本上只是告诉编译器“我不知道这会是什么,只是假设它可能是任何派生自此类/接口,kthxbye”。它没有声明您可以在方法中使用的任何参数,没有您可以调用的标识符,什么都没有。然而,类型参数正是这样做的,如果你声明一个新的,它与仅仅“调用”你不必声明的通配符不同。

其次,考虑如何为泛型类声明类型参数。你觉得这样就够了吗?

public class Foo {
    public T extends CharSequence getBar() {...}
}
public class Foo {
    public <T extends CharSequence> getBar() {...}
}

不,这两个选项都不起作用。为了在类中使用泛型类型参数,您必须将其与类型本身一起声明,而不是与使用它们的方法/字段一起声明。像这样:

public class Foo<T extends CharSequence> {
    public T getBar() {...}
}

为了在方法中使用泛型类型参数,您必须将其与方法本身或包含该方法的类型一起声明,而不是与使用它们的方法参数一起声明。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-10
    • 2019-11-20
    • 2013-05-14
    • 2019-02-14
    • 2020-08-23
    相关资源
    最近更新 更多