我有一个特殊类型的枚举,它定义了一个类,然后该类可以直接从一个枚举值示例化。为实现此目的,每个枚举实现以下接口:
public interface IEnumWithClass {
public Class<?> getAssociatedClass();
}
一个枚举是这样的:
public enum Foo implements IEnumWithClass {
eEnumValue(Goo.class);
private final Class<?> mAssociatedClass;
Foo(Class<?> iAssociatedClass) {
mAssociatedClass = iAssociatedClass;
}
@Override
public Class<?> getAssociatedClass() {
return mAssociatedClass;
}
}
然后可以使用以下帮助程序示例化该类:
public class EnumWithClassHelper extends EnumWithValueHelper {
private static Object getInstance(Class<?> type) throws Exception
{
Constructor<?> constructor = type.getConstructor();
return constructor.newInstance();
}
}
还有一个类似以下的电话:
Goo myGoo = (Goo) EnumWithClassHelper.getInstance( Foo.eEnumValue.getAssociatedClass() );
问题:我想避开这里的演员,直接得到一个黏液。
我使用以下助手制作:
@SuppressWarnings("unchecked")
private static <T> T getInstance(Class<?> type) throws Exception
{
Constructor<?> constructor = type.getConstructor();
return (T) constructor.newInstance();
}
但在本例中,我有一个未经检查的cast异常警告,我也不想要它。
有什么安全的方法吗?还是我要坚持第一种方法?由于接口和枚举限制,我似乎无法将类作为参数传递(我没有成功地为枚举指定泛型参数)。
谢谢!:)
1条答案
按热度按时间jogvjijk1#
不幸的是,由于反射没有任何compiletime类型检查,所以您需要在某个时候进行未检查的强制转换。这又回到了打字的基本原理;jvm不知道它将在代码中示例化的对象的类型(通过设计),直到代码被执行为止,因此不能确定适当的类型是否可用,因为未检查的强制转换将保持未检查状态,这是由于您在接口中使用的泛型所造成的。同时,如果你想使用反射示例化的对象,没有理由不强制转换它,我怀疑你为什么不想要类型强制转换,因为这样做只是确保你拥有的变量实际上是它声称的类型,这只会让你的生活更容易出错。
这个答案可能不令人满意,所以我建议您使用另一个模型:
同时,你的
getInstance
方法可以重新定义为:这允许你打电话
getInstance
使用(例如)ActualFoos.goo.getAssociatedClass()
作为参数直接得到Goo
没有任何强制转换或未选中强制转换的对象。例如,如果我们假设getInstance
是班上的一员Bar
,代码可以如下所示:或者,如果您只引用您知道可以访问的构造函数(可能是public),那么您可以完全放弃helper方法:
tldr公司;有一种方法可以用不同的系统来做你想做的事情,但不能完全用你的系统来做你想做的事情。