<T>T getInstance(final Class<T> type) 为什么不对两者都使用 Class<T>?
<T>T getInstance(final Class<T> type) why not Class<T> for both?
所以,我正在研究 Java 并对这种类型参数的用法感到好奇。
<T>T getInstance
然后是 arg
Class<T> type
我在这里有点困惑,因为如果我们需要一个 return 类型,因此用 T 表示,那么为什么 arg 不一样...例如
private static String getInstance(String arg)
所以我认为会是
private static Class<T> getInstance(final Class<T> type)
所以,我很困惑为什么 return 类型与参数
的表达方式不同
不需要 return 类型与参数类型相同,也绝不是任何规定的规则。
当方法定义为
private static <T> T getInstance(final Class<T> type)
这意味着 return 对象将是 T
类型,而传递给该方法的参数是参数化为 T
的泛型 java.lang.Class
类型的实例].
这意味着可以按如下方式调用该方法:
String string = getInstance(String.class);
因此,此方法采用 Class
类型的实例,并且 returns 是与此 Class
参数对应的类型的对象。
另一方面,当方法定义为
private static <T> T getInstance(final T type)
那么你必须传递一个T
类型的对象来获取实例。想象一下它会这样调用:
String string = getInstance("a");
请注意类型 String
的对象 "a" 与类型 Class
.
的对象 String.class
有何不同
想一想该方法的作用:它 return 是 Class
的 instance
。
用法:
final String string = getInstance(String.class);
那么 return 是什么 - 嗯,它是 String
。参数是什么 - 它是 class String
,由 Class<String>
.
表示
所以方法签名变成:
String getInstance(Class<String> string);
将 String
参数化为 T
为您提供问题中的签名。
T
和Class<T>
完全不同。
第一个说,"an object of some type, T." 第二个说,"an object of type java.lang.Class
, which represents the class for some type T
."
换句话说,这里有两种可能的实现方式:
Class<T> getInstance(Class<T> type) {
return type;
}
T getInstance(Class<T> type) {
return type.newInstance();
}
例如,如果 T
是 String
,那么第一个将 return String.class
,第二个将 return 为空字符串,""
.
这是 Java 实现的一个技巧,当您必须在类型擦除的泛型方法中创建对象时,它可以解决先有鸡还是先有蛋的问题。
Class<T>
是通用的,因此您可以以类型安全的方式调用 getInstance
。如果 Class
中没有 <T>
,你所有的 T
都会被删除,只剩下
Object getInstance() {...}
并且无法获取已被删除的 class T
的引用。
传递 Class<T>
解决了这个问题,因为现在擦除的签名看起来像这样:
Object getInstance(Class cl) {...}
虽然类型又被抹掉了,但是现在你有一个Class
对象,可以作为"factory"来制作classT
的新对象。 Class<T>
在它创建的类型上是通用的这一事实让 Java 编译器执行类型检查,确保编译器隐式插入的转换在运行时成功。
您应该将 class 与其 实例 区分开来。这可能很棘手,因为在 Java 中,classes 也是对象,因此它们也有一个 class(class 的 class!)。说:
class Foo { ... }
- Foo 的实例具有 Foo 类型;
- class
Foo
本身是另一个 class 的(唯一)实例,准确地说是 Class<Foo>
.
所以在上面的声明中,从左到右:
<T>
为泛型参数,使方法成为泛型方法;
T
是 return 类型:方法 return 是 class T
; 的实例
getInstance
是方法名;
Class<T>
意味着您必须将 class T
的(唯一)实例作为参数传递,它本身具有 class Class<Foo>
.
您可以通过隐式静态字段访问此类单例实例Foo.class
。每个声明的 class 都有它,尽管您不会在源代码中找到它(棘手的反射问题)。
最后,为什么 Class
是通用的?好吧,有这样的东西:
package java.lang;
public final class Class<T> {
public static T newInstance();
...
}
so Foo.class.newInstance()
returns a Foo
, Baz.class.newInstance()
returns a Baz
, 依此类推。很整洁,不是吗?
所以,我正在研究 Java 并对这种类型参数的用法感到好奇。
<T>T getInstance
然后是 arg
Class<T> type
我在这里有点困惑,因为如果我们需要一个 return 类型,因此用 T 表示,那么为什么 arg 不一样...例如
private static String getInstance(String arg)
所以我认为会是
private static Class<T> getInstance(final Class<T> type)
所以,我很困惑为什么 return 类型与参数
的表达方式不同不需要 return 类型与参数类型相同,也绝不是任何规定的规则。
当方法定义为
private static <T> T getInstance(final Class<T> type)
这意味着 return 对象将是 T
类型,而传递给该方法的参数是参数化为 T
的泛型 java.lang.Class
类型的实例].
这意味着可以按如下方式调用该方法:
String string = getInstance(String.class);
因此,此方法采用 Class
类型的实例,并且 returns 是与此 Class
参数对应的类型的对象。
另一方面,当方法定义为
private static <T> T getInstance(final T type)
那么你必须传递一个T
类型的对象来获取实例。想象一下它会这样调用:
String string = getInstance("a");
请注意类型 String
的对象 "a" 与类型 Class
.
String.class
有何不同
想一想该方法的作用:它 return 是 Class
的 instance
。
用法:
final String string = getInstance(String.class);
那么 return 是什么 - 嗯,它是 String
。参数是什么 - 它是 class String
,由 Class<String>
.
所以方法签名变成:
String getInstance(Class<String> string);
将 String
参数化为 T
为您提供问题中的签名。
T
和Class<T>
完全不同。
第一个说,"an object of some type, T." 第二个说,"an object of type java.lang.Class
, which represents the class for some type T
."
换句话说,这里有两种可能的实现方式:
Class<T> getInstance(Class<T> type) {
return type;
}
T getInstance(Class<T> type) {
return type.newInstance();
}
例如,如果 T
是 String
,那么第一个将 return String.class
,第二个将 return 为空字符串,""
.
这是 Java 实现的一个技巧,当您必须在类型擦除的泛型方法中创建对象时,它可以解决先有鸡还是先有蛋的问题。
Class<T>
是通用的,因此您可以以类型安全的方式调用 getInstance
。如果 Class
中没有 <T>
,你所有的 T
都会被删除,只剩下
Object getInstance() {...}
并且无法获取已被删除的 class T
的引用。
传递 Class<T>
解决了这个问题,因为现在擦除的签名看起来像这样:
Object getInstance(Class cl) {...}
虽然类型又被抹掉了,但是现在你有一个Class
对象,可以作为"factory"来制作classT
的新对象。 Class<T>
在它创建的类型上是通用的这一事实让 Java 编译器执行类型检查,确保编译器隐式插入的转换在运行时成功。
您应该将 class 与其 实例 区分开来。这可能很棘手,因为在 Java 中,classes 也是对象,因此它们也有一个 class(class 的 class!)。说:
class Foo { ... }
- Foo 的实例具有 Foo 类型;
- class
Foo
本身是另一个 class 的(唯一)实例,准确地说是Class<Foo>
.
所以在上面的声明中,从左到右:
<T>
为泛型参数,使方法成为泛型方法;T
是 return 类型:方法 return 是 classT
; 的实例
getInstance
是方法名;Class<T>
意味着您必须将 classT
的(唯一)实例作为参数传递,它本身具有 classClass<Foo>
.
您可以通过隐式静态字段访问此类单例实例Foo.class
。每个声明的 class 都有它,尽管您不会在源代码中找到它(棘手的反射问题)。
最后,为什么 Class
是通用的?好吧,有这样的东西:
package java.lang;
public final class Class<T> {
public static T newInstance();
...
}
so Foo.class.newInstance()
returns a Foo
, Baz.class.newInstance()
returns a Baz
, 依此类推。很整洁,不是吗?