所以,我正在深入研究Java并对这种类型参数的使用感到好奇。
<T>T getInstance
然后是arg
Class<T> type
我在这里有点困惑,因为如果我们需要一个返回类型,由T表示那么为什么arg不是相同的...例如
private static String getInstance(String arg)
所以我认为它会是
private static Class<T> getInstance(final Class<T> type)
所以,我很困惑为什么返回类型与参数
的表达式不同答案 0 :(得分:7)
不需要使返回类型与参数类型相同,也不需要任何规则来指示。
当方法定义为
时private static <T> T getInstance(final Class<T> type)
这意味着返回对象的类型为T
,而传递给该方法的参数是参数化为java.lang.Class
的通用T
类型的实例。
这意味着可以按如下方式调用该方法:
String string = getInstance(String.class);
因此,此方法采用类型为Class
的实例,并返回与此Class
参数对应的类型的对象。
另一方面,当方法定义为
时private static <T> T getInstance(final T type)
然后你被迫传递T
类型的对象以获取实例。想象一下,它将被调用如下:
String string = getInstance("a");
请注意String
类型的对象“a”与类型String.class
的{{1}}的完全不同。
答案 1 :(得分:4)
T
和Class<T>
完全不同。
第一个说,“某种类型的物体,T”。第二个说,“java.lang.Class
类型的对象,它代表某种类型T
的类。”
换句话说,这里有两种可能的实现:
Class<T> getInstance(Class<T> type) {
return type;
}
T getInstance(Class<T> type) {
return type.newInstance();
}
例如,如果T
是String
,则其中第一个将返回String.class
,第二个将返回空字符串""
。
答案 2 :(得分:3)
想一想该方法的作用:它从instance
返回Class
。
用法:
final String string = getInstance(String.class);
那么回报是什么 - 它是String
。问题是什么 - 它是class String
,由Class<String>
表示。
因此方法签名变为:
String getInstance(Class<String> string);
将String
标准化为T
会在您的问题中为您提供签名。
答案 3 :(得分:2)
当你必须在类型擦除的泛型方法中创建一个对象时,这是Java已经实现的一个技巧来解决鸡与蛋的问题。
Class<T>
是通用的,因此您可以以类型安全的方式调用getInstance
。如果<T>
Class
中没有T
,您的所有Object getInstance() {...}
都会被删除,请留下
T
并且无法获得已被删除的类Class<T>
的引用。
传递Object getInstance(Class cl) {...}
解决了这个问题,因为现在删除的签名如下所示:
Class
虽然类型再次被删除,但现在你有一个T
对象,它可以用作&#34;工厂&#34;制作班级Class<T>
的新对象。 {{1}}在其创建的类型上是通用的这一事实允许Java编译器执行类型检查,确保编译器隐式插入的强制转换将在运行时成功。
答案 4 :(得分:2)
您应该将类与其实例区分开来。它可能很棘手,因为在Java类中也是对象,因此它们也有一个类(类的类!)。说:
class Foo { ... }
Foo
本身是另一个类的(唯一)实例,正好是Class<Foo>
。所以在上面的声明中,从左到右:
<T>
是通用参数,使该方法成为通用方法; T
是返回类型:该方法返回类T
的实例; getInstance
是方法的名称; Class<T>
表示您必须将类T
的(仅)实例作为参数传递,该类本身具有类Class<Foo>
。您可以通过隐式静态字段Foo.class
访问此单例实例。每个声明的类都有它,虽然你不会在源代码中找到它(棘手的反射问题)。
最后,为什么Class
是通用的?好吧,有类似的东西:
package java.lang;
public final class Class<T> {
public static T newInstance();
...
}
所以Foo.class.newInstance()
返回Foo
,Baz.class.newInstance()
返回Baz
,依此类推。干净,不是吗?