【问题标题】:Is there a clean way to assign the Class of a generic type to a variable?有没有一种干净的方法可以将泛型类型的类分配给变量?
【发布时间】:2012-06-16 03:17:38
【问题描述】:

鉴于此代码:

List<Integer> ints = new ArrayList<Integer>();

// Type mismatch: 
// cannot convert from Class<capture#1-of ? extends List> to Class<List<Integer>>       
Class<List<Integer>> typeTry1 = ints.getClass(); 

// Type safety: 
// Unchecked cast from Class<capture#2-of ? extends List> to Class<List<Integer>>
Class<List<Integer>> typeTry2 = (Class<List<Integer>>) ints.getClass();

// List is a raw type. References to generic type List<E> should be parameterized
Class<? extends List> typeTry3 = ints.getClass(); 

有没有办法在没有错误或警告的情况下获得List&lt;Integer&gt;Class?我可以很容易地抑制警告,但如果 Java 要求我抑制这个有效代码的警告,我非常喜欢disappoint

另一方面,如果警告抑制是唯一的方法,那么什么是最安全的抑制呢?

【问题讨论】:

  • 显然没有警告免费方式,因为擦除。 stackoverflow.com/questions/339699/…
  • 对于 Class 对象引用使用具体的泛型类型确实没有意义,因为该信息在被引用的对象中不存在,所以在我看来 Class&lt;? extends List&gt;Class&lt;? extends List&lt;?&gt;&gt; 是变量的最佳类型。尽管我找不到通配符目标类型的无警告强制转换,但我感到很惊讶......但是,由于 Class 对象主要用于反射,所以使用 Class&lt;?&gt; 可能会很好,它可以在没有警告的情况下工作跨度>

标签: java generics


【解决方案1】:

这是 Java 中真正的 Catch-22。

如果您不向List 添加泛型类型,编译器会发出警告:

// WARN: List is not typed
Class<? extends List> typeTry3 = ints.getClass();

这是因为,在大多数情况下,最好输入您的列表。

但是,由于类型擦除,Java 无法在运行时确定 List 的泛型类型,编译器知道这一点。因此,Class 上没有返回类型化对象的方法:

// ERROR: ints.getClass() doesn't return a Class<List<Integer>>, it returns a Class<List>
Class<? extends List<? extends Integer>> var = ints.getClass();

所以您必须将其转换为类型列表。但是,如您所知,由于没有运行时类型检查,Java 会警告您任何类型化变量的强制转换:

// WARN: Casting to typed List
Class<List<Integer>> typeTry2 = (Class<List<Integer>>) ints.getClass();

任何解决这个问题的尝试本质上都是混淆编译器的一种手段,并且不可避免地会令人费解。

那么你最好的选择是选择选项 B:

另一方面,如果警告抑制是唯一的方法,那么什么是最安全的抑制?

抑制此警告的最安全方法是使您的 @SuppressWarnings("unchecked") 注释尽可能本地化。将它们放在每个未经检查的演员之上。这样一来,就绝对清楚是谁造成了警告。

【讨论】:

    【解决方案2】:

    一种方法是创建您的own class。我不确定这是否能满足您的需求。

    我不太确定您要达到的目标。所以也许wildcards 就是答案。

    import java.util.*;
    
    class Main
    {
          public static void main(String[] args)
          {
                List<Integer> list = new ArrayList<Integer>();
                Class<?> clazz = list.getClass();
                System.out.println(clazz) ;
          }
    }
    

    【讨论】:

    • 在我看来,告诉编译器是一个公平的解决方案:“我知道我会得到一个 something 类,请不要抱怨地给我,即使(编译器)可能无法推断/保留这个something”的类型。
    猜你喜欢
    • 2020-02-26
    • 1970-01-01
    • 2021-08-12
    • 1970-01-01
    • 2011-02-07
    • 2018-05-06
    • 2019-12-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多