【问题标题】:How to convert Class<?> to Generics type [closed]如何将 Class<?> 转换为泛型类型 [关闭]
【发布时间】:2021-04-20 05:40:21
【问题描述】:

我有一种方法返回Class&lt;? extends Animal&gt;

public Class<? extends Animal> getAnimal(Animal animal)
{
    //....
}

在参数passGenericAnimal(D animal); 中接受泛型的另一种方法

我想从 getAnimal() 方法中获取 Animal 类类型,我只想通过将其转换为泛型类型来传递给 passGenericAnimal() 方法。

像这样:

public Class<? extends Animal> getAnimal()
{
    return Lion.class;
}

public <T extends Animal> void convertToGenericsAndAssign()
{
    T animal = getAnimal();
    //getting error here
    //Type mismatch: cannot convert from Class<capture#15-of ? extends Animal> to T
    passString(animal);
}

public void passGenericAnimal(D animal)
{
    //....;
}

有什么方法可以将 Class 类型转换为 Generics 类型?

【问题讨论】:

  • 什么是D?你在passString做什么?你能更详细地解释一下吗?我认为我们需要更多地了解您对类对象所做的事情才能回答您的问题。
  • 实际上,? extends 可以是任何东西,我的意思是它可以是我创建的自定义类。例如。 An Animal 是 All animals 的父类,我可以说Class &lt;? extends Animal&gt;,不是吗?
  • 修改了我的问题,希望能帮助你理解场景。
  • 你必须强制转换(T),但是没有办法让这个类型安全。您对? 类型一无所知,尤其是当它与通用T 匹配时。如果类型匹配,它将编译并工作,如果不匹配,它将在运行时崩溃。也就是说,你正在混合不同的东西。你说你有Class&lt;...&gt;,然后想要T 而不是Class&lt;T&gt;,这是两个不同的东西。 Class&lt;Lion&gt; 不是 Lion

标签: java generics casting


【解决方案1】:

我可以给你一些关于如何编译的提示,但我怀疑你在任何情况下都走错了路。即使您的代码编译(并运行)它也可能不会做您认为它会做的事情。但是,目前,只是编译更改:

public Class<? extends Something> getSomeClass() {
    return SomethingSpecific.class;
}

public void convertToGenericsAndAssign() {
    Class<? extends Something> str = getSomeClass();
    // you are getting a class object. You need to actually store a class to make it work.
    passString(str);
}

public <D extends Something> void passString(Class<D> strType) {
    // ....;
}

public static class Something {}

public static class SomethingSpecific extends Something {}

我将类型从String(不可扩展)更改为Something

正如您在示例中看到的那样,问题在于,您实际上从您的方法中获得了 Class 对象。我不完全确定您为什么期望实际对象的实例。 如果你想实例化该类的一个对象,那么下面的代码可能会有所帮助:

public Class<? extends Something> getSomeClass() {
    return SomethingSpecific.class;
}

public void convertToGenericsAndAssign() {
    Class<? extends Something> someClass = getSomeClass();
    // try to get an parameter free constructor:
    
    try {
        Constructor<? extends Something> constructor = someClass.getConstructor();
        Something instance = constructor.newInstance();
        
        // Be aware, that the generic type `D` i smore or less just `Something`,
        // because the compiler cannot know at compile time, what subclass of `Something`
        // D should actually be. So it can just induce `Something`.
        passSomething(instance);
        
    } catch (NoSuchMethodException e) {
        // Handle , if the class does not have an empty constructor.
        e.printStackTrace();
        
    } catch (SecurityException e) {
        // Handle, if the constructor is not accessible, or if the
        // VM does not allow reflection.
        e.printStackTrace();

    } catch (InstantiationException e) {
        // Handle, if the instance failed to be created.
        e.printStackTrace();
        
    } catch (IllegalAccessException e) {
        // Handle, if the metohd is e.g. private or something.
        e.printStackTrace();
        
    } catch (IllegalArgumentException e) {
        // This should not be thrown, as you pass no arguments, but
        // you still have to catch it.
        e.printStackTrace();
        
    } catch (InvocationTargetException e) {
        // If the constructor threw an internal exception.
        e.printStackTrace();
    }
}

public <D extends Something> void passSomething(D strType) {
    // ....;
}

public static class Something {}

public static class SomethingSpecific extends Something {}

【讨论】:

  • OPs passString 方法采用 T 而不是 Class&lt;T&gt;。 IE。他想给方法一个Lion(在他的例子中)和一个Class&lt;Lion&gt;(这当然是不可能的)。
  • @Zabuzard 我知道,这就是我说“让它编译”的原因,但在功能上不一定是他所期望的。但我认为编译示例可能有助于 OP 理解他们面临的问题。
  • 或者你可以抓住ReflectiveOperationException,它涵盖了所有这些。
  • 当然,或者完全捕获Exception,但根据异常类型,OP 可能需要不同的补偿行为。这些只是捕获存根。
猜你喜欢
  • 2018-08-24
  • 1970-01-01
  • 1970-01-01
  • 2020-02-10
  • 1970-01-01
  • 1970-01-01
  • 2018-02-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多