<?> vs <T>

Sch*_*jer 7 java generics

我偶然发现了一个看起来像这样的函数:

public void function(Class<?> clazz) {...}
Run Code Online (Sandbox Code Playgroud)

将方法更改为以下内容的优缺点是什么?

public <T> void function(Class<T> clazz) {...}
Run Code Online (Sandbox Code Playgroud)

编辑:什么是编译时/运行时差异.

Tod*_*d R 10

使用"?" 与"任何"相同,而"T"表示"特定类型".所以,比较这些接口:

public interface StrictClass<T> {
 public T doFunction(Class<T> class);
}

public interface EasyClass<T> {
 public > doFunction(Class<?> class);
}
Run Code Online (Sandbox Code Playgroud)

现在,我们可以创建类:

public class MyStrictClass implements StrictClass<String> {
  public String doFunction(Class<String> stringClass) {
    //do something here that returns String
  }
}

public class MyEasyClass implements EasyClass<String> {
  public String doFunction(Class<?> anyClass) {
    //do something here that returns String
  }
}
Run Code Online (Sandbox Code Playgroud)

希望有所帮助!

  • 另外,“class”不能用作变量名,因为它是保留字。 (2认同)

P. *_*ore 7

todd.run完全正确,但这只是答案的一半.也有使用案例,选择<T><?>(反之亦然),适用,当你不类型参数添加于包封方法的类.例如,考虑之间的区别

public <E extends JLabel> boolean add(List<E> j) {
    boolean t = true;
    for (JLabel b : j) {
        if (b instanceof JLabel) {
            t = t && labels.add(b);
        }
    }
    return t;
}
Run Code Online (Sandbox Code Playgroud)

public boolean add(List<? extends JLabel> j) {
    boolean t = true;
    for (JLabel b : j) {
        if (b instanceof JLabel) {
            t = t && labels.add(b);
        }
    }
    return t;
}
Run Code Online (Sandbox Code Playgroud)

第一种方法实际上不会编译,除非您向封闭类添加适当的类型参数,而第二种方法将编译,无论封闭类是否具有类型参数.如果您不使用<?>,那么您在本地负责告诉编译器如何获取将由其所在位置使用的字母填写的类型.你经常遇到这个问题 - 需要使用吗?而不是T - 当试图编写使用或需要"扩展"和"超级"的泛型方法时.Gilad Bracha的泛型教程(PDF)第18页对此问题进行了更好但更精细的处理.另请参阅此堆栈溢出问题,其答案阐明了这些问题.

查看此堆栈溢出链接,了解有关第二个问题的信息:Java泛型 - 类型擦除 - 何时以及发生了什么.虽然我不知道答案,你对之间的编译时间差的问题<?>,并<T>,我敢肯定的答案,可以发现这个FAQ是埃里克森在文章中提到.