Java 无法进行泛化时,正确转换为作为参数传递的未知类型

Java 无法进行泛化时,正确转换为作为参数传递的未知类型,java,generics,reflection,enums,interface,Java,Generics,Reflection,Enums,Interface,我有一个特殊类型的枚举,它定义了一个类,然后该类可以直接从枚举值实例化。为实现此目的,每个枚举实现以下接口: public interface IEnumWithClass { public Class<?> getAssociatedClass(); } 问题:我想避开这里的演员阵容,直接得到一个好的 我使用以下帮助器创建了它: public class EnumWithClassHelper extends EnumWithValueHelper { priva

我有一个特殊类型的枚举,它定义了一个类,然后该类可以直接从枚举值实例化。为实现此目的,每个枚举实现以下接口:

public interface IEnumWithClass {
    public Class<?> getAssociatedClass();
}
问题:我想避开这里的演员阵容,直接得到一个好的

我使用以下帮助器创建了它:

public class EnumWithClassHelper extends EnumWithValueHelper {
    private static Object getInstance(Class<?> type) throws Exception
    {    
        Constructor<?> constructor  = type.getConstructor();        
        return constructor.newInstance();
    }   
}
@SuppressWarnings("unchecked")
private static <T> T getInstance(Class<?> type) throws Exception
{    
    Constructor<?> constructor  = type.getConstructor();        
    return (T) constructor.newInstance();
}
@SuppressWarnings(“未选中”)
私有静态getInstance(类类型)引发异常
{    
Constructor=type.getConstructor();
return(T)constructor.newInstance();
}
但在本例中,我有一个未经检查的强制转换异常警告,我也不想要它

有什么安全的方法吗?还是我要坚持第一种解决方案?由于接口和枚举限制,我似乎无法将类作为参数传递(我没有成功地为枚举指定泛型参数)


谢谢!:)

不幸的是,由于任何compiletime类型检查都不附带反射,因此您需要在某个时候进行未经检查的强制转换。这又回到了打字的基本原理;JVM不知道它将在代码中实例化的对象的类型(通过设计),直到代码被执行,因此,无法确保适当的类型可用,因为未选中的强制转换将保持未选中状态,因为您在接口中使用的泛型。同时,如果您打算使用反射式实例化的对象,那么没有理由不强制转换它,我质疑您为什么不希望进行类型强制转换,因为所做的只是确保您拥有的变量实际上是它声称的类型,这只会让您在错误方面更轻松

这个答案可能不令人满意,因此我建议您使用另一个模型:

public interface IEnumWithClass<T> {
    public Class<T> getAssociatedClass();
}

public abstract class Foo<T> implements IEnumWithClass<T> {
    // Put any other code that shouldn't be instance-specific here
}

public final class ActualFoos{
    public static final Foo<Goo> goo = new Foo<Goo>() {
        @Override
        public Class<String> getAssociatedClass() {
            return Goo.class;
        }
    };
    public static final Foo<Integer> integer = new Foo<Integer>() {
        @Override
        public Class<Integer> getAssociatedClass() {
            return Integer.class;
        }
    };
}
这允许您使用(例如)
ActualFoos.goo.getAssociatedClass()
作为参数调用
getInstance
,并直接获取
goo
对象,而不进行任何强制转换或未选中的强制转换。因此,例如,如果我们假设方法
getInstance
是类
Bar
的一部分,那么代码可能如下所示:

public enum Foo implements IEnumWithClass {

    eEnumValue(Goo.class);

    private final Class<?>    mAssociatedClass;

    Foo(Class<?> iAssociatedClass) {
        mAssociatedClass = iAssociatedClass;
    }

    @Override
    public Class<?> getAssociatedClass() {
        return mAssociatedClass;
    }
}
Goo g = Bar.getInstance(ActualFoos.goo.getAssociatedClass());
或者,如果您只引用您知道可以访问的构造函数(可能是public),那么您可以完全放弃helper方法:

Goo g = ActualFoos.goo.getAssociatedClass().getConstructor().newInstance();

TLDR;有一种方法可以使用不同的系统实现某种程度上的目的,但不能完全实现使用系统时的目的。

这:
SolverArchitectures(类IASociatedClass){MassSociatedClass=IASociatedClass;}
不应编译。它是
Foo
enum声明中的
SolverArchitectures
构造函数。如果由于“接口和枚举限制”而无法提供任何更多的泛型类型信息,则必须执行未经检查的强制转换。这里需要使用枚举有什么特别的原因吗?或者你可以只使用一个带有私有构造函数的类来阻止其他人创建实例吗?大卫:谢谢,我修复了这个例子。安迪:我们使用枚举是因为信息是在不同语言的插件之间共享的。有时我们甚至不知道要处理哪个枚举,因为它取决于用户设置(枚举本身有时直接使用,有时使用工厂方法和助手进行实例化)。在枚举中包含一个类规范可以避免长时间频繁的切换情况;不是专门的
enum
。特别是当您在Java以外的语言中使用它们时。您可以创建一组固定的值,而无需使用
enum
。我可以对此进行调查,任何链接都可以提供建议?我非常喜欢您的答案,但我需要一些模拟枚举值的东西,有人谈到了集合,但我仍然没有时间进行调查。在您的示例中,我假设嵌套类中Foo的各种实现扮演枚举的角色,但在访问嵌套类之前,我需要实例化AcutalFoo,这需要在Matlab中完成。我必须调查这是如何工作的,谢谢!在我的示例中,
ActualFoos
类只包含静态字段,这意味着您不需要类的实例来访问字段。这样,它将非常类似于枚举。唯一明显的区别(除了一些方便的方法,比如在内部数组中获取枚举的索引)是类
Foo
仍然可以在
ActualFoos
类之外实例化。要消除这种情况,请考虑:非常好,谢谢,我将很快尝试一下,并可能用它替换我的枚举系统。
Goo g = Bar.getInstance(ActualFoos.goo.getAssociatedClass());
Goo g = ActualFoos.goo.getAssociatedClass().getConstructor().newInstance();