【问题标题】:Get Java Class name from generic List type从泛型 List 类型获取 Java 类名
【发布时间】:2014-01-24 17:57:20
【问题描述】:

我有一个方法,里面有 1 个列表,泛型类:

public static String classTypeOfList(List<T> list) {
    return T.getName(); //in my mind...
}

代码是错误的,但你可以看到,我想要什么。如果我这样调用这个方法:

List<MyObject> list;
System.out.println("the type of the list is: "+classTypeOfList(list));

我想得到这个结果:

the type of the list is: MyObject

如何获得泛型类型类的名称?或者如果我不能通过这种方式得到它,那么你能告诉我另一个选择吗? 谢谢!

【问题讨论】:

  • 你不能在编译时将它们删除。
  • 使用 getClass() 方法在运行时为您提供类名

标签: java generics generic-list


【解决方案1】:

由于Type Erasure,您将无法获取类型(在空列表的情况下)。正如 JLS 在类型擦除中所说:

4.6。类型擦除

类型擦除是类型的映射(可能包括参数化 类型和类型变量)到类型(从不参数化类型 或类型变量)。我们写 |T|对于类型 T 的擦除。 擦除映射定义如下:

The erasure of a parameterized type (§4.5) G<T1,...,Tn> is |G|.

The erasure of a nested type T.C is |T|.C.

The erasure of an array type T[] is |T|[].

The erasure of a type variable (§4.4) is the erasure of its leftmost bound.

The erasure of every other type is the type itself.

类型擦除还映射构造函数的签名(第 8.4.2 节)或 没有参数化类型或类型的签名的方法 变量。构造函数或方法签名 s 的擦除是 签名由与 s 相同的名称和所有的擦除组成 s中给出的形参类型。

构造函数或方法的类型参数(第 8.4.4 节),以及 方法的返回类型(第 8.4.5 节),如果 构造函数或方法的签名被删除。

泛型方法签名的擦除没有类型 参数。

如果是非空列表:

......
public static void main(String[] args) throws ClassNotFoundException {

List<MyObject> list= new ArrayList<MyObject>();
        list.add(new MyObject());
        System.out.println("the type of the list is: "+classTypeOfList(list));
}

public static <T> String classTypeOfList(List<T> list) throws ClassNotFoundException {
        return list.get(0).getClass().getCanonicalName(); 
}

输出

the type of the list is: MyObject

【讨论】:

  • "In case of Non Empty List:" 通常不起作用,因为 1) list.get(0) 可能是 null,并且 2) list.get(0).getClass() 可能是 T 的子类跨度>
【解决方案2】:

恐怕,这做不到。泛型仅在编译时存在。在运行时此信息会被删除,在运行时您的List&lt;MyObject&gt; 将简单地变成List

【讨论】:

    【解决方案3】:

    这个答案可能与问题很少(或非常)不同,因为它足够长的评论,所以我将其发布为答案。

    我发现这个问题很有趣,因此尝试了一下。我的尝试如下,我得到了班级的Type,所以我认为值得分享并让专家对我的方法发表意见

    public class A {
        public static void main(String[] args) {
    
        List<B> listB = new ArrayList<>();
        B b1 = new B();
        listB.add(b1);
    
        List<C> listC = new ArrayList<>();
        C c1 = new C();
        listC.add(c1);
    
        A a = new A();
        a.method(listB);
        a.method(listC);
    
    }
    
    public <T> void method(List<T> list) {
    
        System.out.println(list.get(0).getClass().getName());
    }
    }
    
    class B {
    
    }
    
    class C {
    
    }
    

    我得到的输出是BC

    【讨论】:

    • 这通常不起作用,因为 1) list 可能在索引 0 处没有元素,2) list.get(0) 可能是 null,并且 3) list.get(0).getClass() 可能是子类T
    【解决方案4】:

    您需要在对象上使用getClass()。获得类对象后,您可以使用getName() 检索类名。

    【讨论】:

    • “关于对象”什么对象?
    【解决方案5】:

    这是上课的方式:

    Class<T> clazz = ((Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]);
    

    您可以在link 上阅读更多相关信息。

    【讨论】:

    • 这与这个问题无关。这仅适用于对象是实现具有特定类型参数的接口的子类的情况。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-17
    • 1970-01-01
    • 2011-01-24
    • 2011-05-11
    • 1970-01-01
    相关资源
    最近更新 更多