【问题标题】:how to declare Class.class with valid generics如何使用有效的泛型声明 Class.class
【发布时间】:2011-05-19 23:33:49
【问题描述】:

注意:纯粹出于好奇,并非针对任何实际用例。

我想知道是否有办法用有效的类型参数声明 Class Class 对象:

Class cc1 = Class.class; //raw type
Class<Class> cc2 = Class.class; //now parameter is raw type
Class<Class<?>> cc3 = Class.class; //compile error: inconvertible types

如果ClassClass&lt;?&gt; 可以互换,为什么Class&lt;Class&gt;Class&lt;Class&lt;?&gt;&gt; 不能互换?

编辑:这个问题可以概括为嵌套原始类型参数的问题。例如:

ArrayList<ArrayList<?>> lst = new ArrayList<ArrayList>(); //same compile error

EDIT2:我应该重新表述一下这个问题:我知道

Class<?> c = Class.class;

是有效的,但我想知道为什么 Class&lt;Class&gt;Class&lt;Class&lt;?&gt;&gt; 不一样

【问题讨论】:

    标签: java generics nested-generics


    【解决方案1】:

    泛型有一些非常严重的限制。在这种情况下,您不能将类型分配给 Class&lt;Class&gt; 的内部类型,因为您实际上是在引用原始类型,而不是原始类型的实现。它会给您一个警告,但您无法修复该警告。

    Class&lt;Class&lt;?&gt;&gt; 本身不是不可转换的类型,你不能直接为它分配一个类,因为它没有Class&lt;Class&lt;T&gt;&gt; 类型,它有Class&lt;T&gt; 类型。

    换个角度想;试试List&lt;List&lt;String&gt;&gt;。要创建它,您需要创建一个包含字符串列表的列表。这是可行的,因为列表可以包含列表。

    Class 更像是一个原始数据对象而不是数据对象,所以我认为不可能创建一个 Class 类型为其他类型的 Class。

    编辑:您关于ArrayList&lt;ArrayList&lt;?&gt;&gt; 的额外问题是您在Class&lt;Class&lt;?&gt;&gt; 中遇到的不可转换类型问题的一个更明显的例子。

    【讨论】:

    • 上面的答案给出了泛型/通配符的详细解释,但这一个最接近我的要求,这就是为什么 Class 与 Class> 不同。谢谢大家
    【解决方案2】:

    这里的规则是左侧的泛型类型必须与右侧的泛型类型匹配。

    Class&lt;?&gt; 表示任何类型的类。

    Class<?> c = Class.class; 
    

    之所以有效,是因为任何类型的类都可以是Class&lt;Class&gt;

    Class<Class<?>> cc3 = Class.class;
    

    不工作,因为 Class.class 类型是 Class&lt;Class&gt; 而不是 Class&lt;Class&lt;?&gt;&gt; 类型

    ArrayList<ArrayList<Integer>> lst = new ArrayList<ArrayList<Integer>>();
    ArrayList<ArrayList<?>> lst = new ArrayList<ArrayList<?>>();
    

    有效,因为这两个表达式匹配。

    ArrayList<ArrayList<?>> lst = new ArrayList<ArrayList>();
    

    不匹配。

    【讨论】:

      【解决方案3】:

      很难确切地看到你在问什么(或者你想做什么)。但你可以在没有原始类型的情况下进行参数化。

      Class<? extends Object> cc4 = Class.class; // no raw types
      Class<?> cc5 = Class.class; // also an option
      

      就您的最后一个示例而言,这没有任何意义,因为您似乎想要创建一个包含 ? 的数组列表的数组列表,但您的声明并未声明包含数组列表的数组列表?.

      正确编写(但仍然不是正确的 Java)将是:

      ArrayList<ArrayList<?>> lst = new ArrayList<ArrayList<Integer>>(); // Type mismatch
      

      这是预期的。由于同样的原因,它不起作用,如下所示:

      Object o = new Object();
      Integer i = new Integer(3);
      
      o = i;
      i.floatValue();
      o.floatValue(); // can't access that method, we need to specifically cast it to Integer
      

      Java 类型不是主动推断的(即使在继承链中)。

      如果您想保留通配符,欢迎您:

      ArrayList<ArrayList<?>> lst = new ArrayList<ArrayList<?>>(); // works!
      

      【讨论】:

      • 完美答案。但我需要指出&lt;? extends Object&gt;&lt;?&gt; 完全相同,这是表达式匹配的唯一原因。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-30
      • 1970-01-01
      • 2012-07-14
      • 1970-01-01
      • 2018-12-14
      • 1970-01-01
      相关资源
      最近更新 更多