简体   繁体   English

ClassCastException:java.lang.Class无法强制转换为java.lang.reflect.ParameterizedType

[英]ClassCastException:java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType

I'm trying to work with generics mostly for practice and for a little idea I had. 我正在尝试使用泛型,主要是为了练习和我有一点想法。 At the moment I have a problem with: ClassCastException:java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType . 目前我遇到了一个问题: ClassCastException:java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType Most of the topics I found about this where from users that posted very specific code. 我发现的大多数主题来自发布非常具体代码的用户。 This makes it really harder for me to understand. 这让我很难理解。 I tried to make the problem as simple as possible but still related to my actual problem. 我试图让问题变得尽可能简单,但仍然与我的实际问题有关。 I hope someone can help. 我希望有人能帮帮忙。

The Bar class: 酒吧班:

class Bar { }

The Foo class: Foo类:

class Foo<T> {

  ArrayList<Object> list;

  Foo(int initialCapacity) {
    init(initialCapacity);
  }

  void init(int initialCapacity) {
    list = new ArrayList<Object>(initialCapacity);

    for (int i = 0; i < initialCapacity; i++) {
      try {
        list.add(((Class)((ParameterizedType)this.getClass().
          getGenericSuperclass()).getActualTypeArguments()[0]).newInstance());
      }
      catch (InstantiationException e) {

      }
      catch (IllegalAccessException e) {

      }
    }


  }

}

use: 使用:

Foo<Bar> com = new Foo<Bar>(100);

You seem to be confused about Generics in Java. 你似乎对Java中的泛型感到困惑。

Java does not implement Generics the same way it is done in, say, C# : you cannot retrieve type information of a generic type at runtime, because it's simply not saved after compilation (see: type erasure ) Java没有像在C#中那样实现Generics:你不能在运行时检索泛型类型的类型信息,因为它在编译后根本就没有保存(参见: type erasure

This means that if I declare a variable of type List<MyObject> , then I cannot know if it is a list of MyObject, because the type information is lost, and the class of this list is just List, which is not implementing ParameterizedType. 这意味着如果我声明一个List<MyObject>类型的变量,那么我不知道它是否是MyObject的列表,因为类型信息丢失了,这个列表的类只是List,它没有实现ParameterizedType。

The only time where the generic type information is saved, is when it is known at compile time for a type definition: 保存泛型类型信息的唯一时间是在编译时知道类型定义:

public class MyList extends List<MyObject> {}

Here, MyList.class.getGenericSuperclass() should be implementing ParameterizedType. 这里, MyList.class.getGenericSuperclass()应该实现ParameterizedType。 I'm afraid that what you are trying to do here is not possible, or at least, it could be working, if init was called on a class inheriting Foo, such as : 我担心你在这里尝试做的事情是不可能的,或者至少,它可能有效,如果在继承Foo的类上调用init,例如:

public class StringFoo extends Foo<String> {
    public StringFoo(int initialCapacity) { 
        super(initialCapacity); 
    }
}

StringFoo foo = new StringFoo(100);

The root of the error is that this in your example is an instance of Foo<String> , whose superclass is the non-parameterized type java.lang.Object . 错误的根源在于您的示例中的thisFoo<String>的实例,其超类是非参数化类型java.lang.Object Thus getGenericSuperclass() is giving you Object.class instead of a ParameterizedType . 因此getGenericSuperclass()为您提供Object.class而不是ParameterizedType

The pattern you're trying to use looks like the " type token " trick used by libraries such as gson where you define an anonymous subclass of the generic type at the point where you want to use it in order to capture the type parameters in the generic superclass signature. 您尝试使用的模式看起来像库这样的“ 类型令牌 ”技巧,例如gson ,您可以在要使用它的位置定义泛型类型的匿名子类,以便捕获类型参数。通用超类签名。 Your code would work if you did 如果你这样做,你的代码就可以了

Foo<Bar> com = new Foo<Bar>(100) {};

The empty braces make this an anonymous class whose generic superclass is the ParameterizedType representing Foo<Bar> . 空括号使它成为一个匿名类,其通用超类是表示Foo<Bar>ParameterizedType

Note that this trick can only work when you instantiate the type parameter with a non-parameterized class literal. 请注意,只有在使用非参数化类文字实例化type参数时,此技巧才有效。 If you had a method like 如果你有像这样的方法

static <E> Foo<E> makeFoo(E element) {
  Foo<E> f = new Foo<E>(100) {};
  // do something with element
}

it would fail because ((ParameterizedType)this.getClass().getGenericSuperclass()) .getActualTypeArguments()[0] would be a TypeVariable rather than a Class . 它会失败,因为((ParameterizedType)this.getClass().getGenericSuperclass()) .getActualTypeArguments()[0]将是TypeVariable而不是Class Similarly 同样

Foo<List<String>> listFoo = new Foo<List<String>>(5){}

would fail because here the first actual type argument is a ParameterizedType rather than a Class . 会失败,因为这里第一个实际的类型参数是ParameterizedType而不是Class

To answer your original question: you are trying to cast an object of the type Type to the type Class . 要回答您的原始问题:您正在尝试将Type的对象Type转换为类Class Since Type is a supertype of Class this results in an exception - what a confusing sentence. 由于TypeClass的超类型,因此会导致异常 - 这是一个令人困惑的句子。

And here comes my second point: Do not use reflection unless you really really have to. 而这才是我的第二点: 不要使用反射,除非你真的不得不这样做。 It's the black magic of java! 这是java的黑魔法! Also as Snaipe points out, and this is the most important thing, due to type erasure reflection will not help you with any problem related to generics. 同样正如Snaipe指出的那样,这是最重要的事情,由于类型擦除反射不会帮助您解决与泛型相关的任何问题。

What you're trying to do is only possible if you subclass Foo , providing an actual value for T that is captured in Foo 's type definition: 你想要做的只有在你为Foo子类化时才有可能,提供在Foo类型定义中捕获的T的实际值:

class StringFoo extends Foo<String> {}

Then init should work as you expect. 然后init应该按预期工作。 Without capturing an actual value for T in a type definition, there's no way to recover the value of T at runtime. 如果没有在类型定义中捕获T的实际值,则无法在运行时恢复T的值。

This is a solution 这是一个解决方案

    public TO getTo() throws Exception{
      if (to == null) {
        try{
            to = ((Class<TO>)((ParameterizedType)this.getClass().
                       getGenericSuperclass()).getActualTypeArguments()[0]).newInstance();
        }catch(ClassCastException cce){
            cce.printStackTrace();
            to = ((Class<TO>)((ParameterizedType)(((Class<TO>)
                    this.getClass().getAnnotatedSuperclass().getType()).getGenericSuperclass()))
                        .getActualTypeArguments()[0]).newInstance();
        }   
      }
      return to;
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 java.lang.ClassCastException:无法将java.lang.Class强制转换为java.lang.reflect.ParameterizedType - java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType java.lang.Class无法强制转换为java.lang.reflect.ParameterizedType - java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType 类不能转换为java.lang.reflect.ParameterizedType - Class cannot be cast to java.lang.reflect.ParameterizedType 嵌套类不能转换为java.lang.reflect.ParameterizedType - Nested class cannot be cast to java.lang.reflect.ParameterizedType 设计模式:Lazy Singleton,Generics和Inheritance:java.lang.Class无法强制转换为java.lang.reflect.ParameterizedType - Design Pattern: Lazy Singleton, Generics and Inheritance: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType Java:ClassCastException-无法将java.lang.Class强制转换为 - Java: ClassCastException - java.lang.Class cannot be cast to 引起:java.lang.ClassCastException:使用Generic Type时,libcore.reflect.ParameterizedTypeImpl无法强制转换为java.lang.Class - Caused by: java.lang.ClassCastException: libcore.reflect.ParameterizedTypeImpl cannot be cast to java.lang.Class when use Generic Type How to fix java.lang.ClassCastException: java.lang.Class cannot be cast to java.util.Map - How to fix java.lang.ClassCastException: java.lang.Class cannot be cast to java.util.Map class java.lang.Class cannot be cast to class java.lang.reflect.Parameterized - class java.lang.Class cannot be cast to class java.lang.reflect.Parameterized 测试DAO时出错:sun.reflect.generics.reflectiveObjects.TypeVariableImpl无法强制转换为java.lang.Class - Error testing DAOs: sun.reflect.generics.reflectiveObjects.TypeVariableImpl cannot be cast to java.lang.Class
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM