java - Class<T> 怎么可能是通用的?

标签 java class generics

Java 类 Class<T>由于以下原因,通用会造成混淆。

想象一个类 Cake<T>{} 所以你可以创造 new Cake<Pineapple>new Cake<Apple> ETC 如果每个类(class) e.x Apple有一个可参数化的类对象,如果类 Class是通用的,那么似乎有可能创建 Apple<Something>Integer<Something> ,这没有任何意义。

我不知道我在这里理解错了什么。看似inception,但更深的层次与上面的层次相同。

假设下面是通用类

public class Cake<T> {
  T cakeType;

  void setCakeType(T cakeArg){
    this.cakeType = cakeArg;
  }

  void doStuff(){
    System.out.println(cakeType.toString());
  }
}

假设 Pineapple 是非泛型类作为 Cake 的参数类型

public class Pineapple {

  @Override
  public String toString() {
    return "I am a Pineapple";
  }
}

如果类Class不是通用的,那么凭直觉,会有 Pineapple Class目的 但是作为类Class<T>本身是通用的。然后似乎有可能创建 Pineapple 的可参数化类对象即Pineapple<Something> .

基本假设:只有一个 Class每个类的对象。对其进行参数化有何意义?

最佳答案

我将尝试通过几种不同的方法来解决这个问题;我认为正在发生的事情之间存在根本性的脱节,因此分散式方法可能更有可能使其中一个点成为“点击”。

层次结构

因此,首先,不要认为 Apple 类对象;相反,有一个 Apple 类,在它旁边还有一个描述它的 Class 对象。但是那个 Class 对象只是独立存在,而不是 Apple 层次结构的一部分。它不是 Apple 的母公司;它是它最好的 friend 。

所有类的基类都是Object,而不是Class。现在,如果 Object 被参数化,那么您将拥有与您所描述的内容一致的内容——但事实并非如此。由于 Class 不是 Apple 层次结构的一部分,因此从逻辑上讲,Class 被参数化并不会使 Apple 参数化。

类比其他泛型类

Class 对象的意义在于谈论其他对象——告诉我们诸如“这是一个 T”或“这是创建 T 的方式”之类的事情。那么,每个实例如何在编译时告诉我们它在谈论哪类事情呢?通过参数。

同样,List 对象的要点是谈论其他对象——将它们放在一个组中。它还使用通用参数来描述它所谈论的事物的种类。使用列表,您可以仅通过类型签名来判断其中的内容:a List<String>List<Integer> 时关注字符串关注整数。好吧,以同样的方式,一个Class<String> Class<Integer> 时谈论字符串谈论整数。 Class 参数化这一事实对 String 或 Integer 的影响并不比 List 参数化这一事实更大。

换句话说:在最高级别,List<String>用字符串做事。 Class<String>也是如此

一些用例

最后,思考为什么类是参数化的可能会有所帮助。 Class 上只有少数方法返回 T类型。让我们来看看其中的两个:

T newInstance()
T cast(Object o);

如果 Class 没有参数化,这两个都将返回 Object。你必须做这样的事情:

Class<Apple> appleClass = ...;
Apple newApple = (Apple) appleClass.newInstance();
Apple existingApple = (Apple) appleClass.cast(existingObject);

好的,这样还算不错。但在这种情况下,我们已经知道我们感兴趣的事物类型(苹果)。这就是我们可以添加 Apple 类型转换的原因,但出于同样的原因,这也是使用 Class<Apple> 的原因。没有用。上面的代码片段最好按以下方式完成:

Apple newApple = new Apple();
Apple existingApple = (Apple) existingObject;

相反,当您使用本身是通用的方法时,类的通用方面通常很有用。例如:

<T> T tryConsume(Consumer<T> consumer, Object item, Class<T> consumeClass) {
  T itemCasted = consumeClass.cast(item);
  consumer.consume(itemCasted);
}

诚然,这个例子不是很有趣。但我要指出的一件事是,如果没有 consumeClass,您将不得不将 item 转换为 (T) .由于type erasure ,这在运行时实际上是一个空操作,如果该项目属于错误的类,则 ClassCastException 将来自 consumer 中一个奇怪的生成行代码 -- 不是来自 tryConsume 内部,它很好而且清晰。做到这一点 cast方法实际上 转换,并且有用,你需要 consumeClass.cast(item)返回 T .为此,consumeClass必须是 Class<T> 类型.

关于java - Class<T> 怎么可能是通用的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44170999/

相关文章:

java - 是什么原因导致 Android Dalvik java.lang.VerifyError "Invalid reg type for array index"?

ios - 无法访问类对象变量

generics - 是否有约定将 ?Sized by 本身写为特征界限?

Java - Binary Search Node 如何检查对象?

java - java中解密加密的二进制文件(AES_CTR模式)

java - java中字符串的空值检查

ios - (Swift) 如何从不同的类中引用一个对象的属性?

c# - 大中型项目的结构

java - 嵌套 Groovy 泛型 : unexpected token on inner generic type

java - <? 之间有什么区别?扩展对象> 和 <E 扩展对象>?