<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 是 Classinstance

用法:

final String string = getInstance(String.class);

那么 return 是什么 - 嗯,它是 String。参数是什么 - 它是 class String,由 Class<String>.

表示

所以方法签名变成:

String getInstance(Class<String> string);

String 参数化为 T 为您提供问题中的签名。

TClass<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();
}

例如,如果 TString,那么第一个将 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, 依此类推。很整洁,不是吗?