如何解释Java中的“public <T> T readObjectData(... Class<T> type)”?

49
我有这段Java代码。
public <T> T readObjectData(ByteBuffer buffer, Class<T> type) {
...
T retVal = (T) summaries;
return retVal;

如何解释这段代码?为什么我们需要public <T> T而不是public T

如何将参数传递给第二个参数(Class<T> type)?

5个回答

63

这个声明将 readObjectData 方法定义为泛型,有一个类型参数 T

public <T> ...

那么返回类型就是 T
... T readObjectData(...

没有初始的 <T>,也就是泛型类型声明,符号 T 将是未定义的。在参数列表中,Class<T> type 是其中之一。由于返回类型和此参数都引用了 T,因此这确保了如果您传递一个 Class<String>,则它将返回一个 String。如果您传递一个 Class<Double>,则它将返回一个 Double。要传递参数,请传递任何 Class 对象,例如 String.class

35

<T> 部分声明了一个 泛型类型参数 T。如果您省略此部分,编译器可能会抱怨 T 类型不存在。

在这种情况下,T 作为实际类型的占位符,该类型只有在使用非泛型类型参数调用方法时才确定。

public <T> T readObjectData(...
        ^  ^
        |  + Return type
        + Generic type argument

21

<T> 是一个参数类。没有名为 T 的类。您可以使用第二个方法参数 type 指定的任何类来使用此方法。

由于方法定义如下:

public <T> T readObjectData(ByteBuffer buffer, Class<T> type)

您可以按照以下方式调用它:

MyClass obj = o.readObjectData(buffer, MyClass.class);

请注意,您不必将 readOjectData() 的返回值强制转换为 MyClass。在 Java 5 之前,该方法会被定义为:

public Object readObjectData(ByteBuffer)

它的用法如下:

MyClass obj = (MyClass)o.readObjectData(buffer);

由于强制转换可能会导致 ClassCastException,这是一种不好的做法。这就是泛型发明的原因。


14

你可能会对类似且更常见的声明感到困惑:

class MyClass<T> {
   private  T myMethod(T a){
       return  a;
   }
}

在上述情况下,在private之后不需要加上""<T>""(private <T> T myMethod(T a)),因为它使用的T与类MyClass<T>中定义的相同。
甚至更进一步,如果你写
class MyClass<T> {
   private <T> T myMethod(T a){
       return  a;
   }
}

那么这意味着myMethod的返回类型可能与MyClass类型不同。就好像你写成这样:

class MyClass<T1> {
   private <T2> T2 myMethod(T2 a){
       return  a;
   }
}

致谢:本文参考了“Kanagavelu Sugumar”在如何在Java中使用Class<T>?问题的更长回答示例。


0

这是JsonPath使用的模式,它允许您使用语义,例如:

String author        = JsonPath.read(json, "$.store.book[0].author");
List<String> authors = JsonPath.read(json, "$.store.book[*].author");

这是在动态编程语言中最接近鸭子类型的东西,比如JavaScript,目前也可以用Java来实现。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接