考虑以下代码:
// ...
public class BaseClass
{
public BaseClass (int theParam)
{
// ...whatever...
}
}
public class DerivedType
{
// ...Content does not matter...
}
// ...elsewhere:
public <ElemType extends BaseClass> boolean doIt (ArrayList<ElemType> target)
{
ElemType newElem=new ElemType (5) ; // "Cannot instantiate this type"
// ...other code does not matter...
return true ;
}
// ..
如何在
ElemType
中创建类型为doIt
的实例?所示的结构产生指示的错误。
ElemType.newInstance
不存在,这使我感到惊讶。我已经阅读了几乎所有的常见问题解答,答案和可谷歌搜索的材料,但是找不到任何有用的信息。
编辑:
是的,我知道反射有其缺点,并且由于多种原因,它不是最终的解决方案。问题不是“我应该做”,而是“我将如何做”。
最佳答案
如上所述,泛型的类型擦除不允许这样做。但是您可以像这样实现您想要的:
public class BaseClass {
public BaseClass(int theParam) {
// ...whatever...
}
public BaseClass() {
}
}
public class DerivedType extends BaseClass {
}
现在doIt()方法获取类参数以供参考:
public <D extends BaseClass> boolean doIt (ArrayList<D> target, Class<D> c)
{
try {
D newElem = c.getDeclaredConstructor(int.class).newInstance(5);
} catch (Exception e) {}
// ...other code does not matter...
return true ;
}
您应该这样称呼它:
ArrayList<DerivedType> testList = new ArrayList<DerivedType>();
testList.add(new DerivedType());
testList.add(new DerivedType());
doIt(testList, DerivedType.class);
希望有帮助:)
请注意,您可能真的很想变黑,摆脱class参数,然后尝试以下操作:
public static <D extends BaseClass> boolean doIt (ArrayList<D> target)
{
try {
D newElem1 = ((Class<D>) ((ParameterizedType) target.getClass().getGenericSuperclass()).getActualTypeArguments()[0]).getDeclaredConstructor(int.class).newInstance(5);
} catch (Exception e) { e.printStackTrace();}
return true ;
}
}
实际上,我在第二次编辑之前就这样认为:)但这引起了“ java.lang.ClassCastException:sun.reflect.generics.reflectiveObjects.TypeVariableImpl无法转换为java.lang.Class”,正如您提到的那样(我没有看到它是因为忽略了catch语句)。简而言之,Java运行时系统不存储参数化类型(有利于向后兼容;因此将来可能会改变)。
因此,看起来如果不“接触”某些课程是不可能的。
但是,除了提到的方法之外,我还能想到另外两件事。首先,如果BaseClass和DerivedType'D'类都实现了clone()方法,则可以从数组中获取对象的副本,然后使用它:
D o = target.get(0);
D oNew = (D)((BaseClass)o).clone();
target.add(oNew);
多态将照顾其余的:)
第二个不是真正的“解决方案”,但是如果您只想作为按类型参数化的对象数组的新实例,则可以使用第二个解决方案。类型擦除仅在参数化类型上发生,而在基本数组上则不发生(数组在JVM中得到了验证)。因此,如果我们可以自由更改方法的签名并且可以使用数组,则可以使用以下方法:
public <D extends BaseClass> boolean doIt(D[] target) {
try {
D newD = (D) (target.getClass().getComponentType().getConstructor(int.class).newInstance(8));
target[0] = newD;
// The following is optional, if we want to work with Collections internally
List<D> l = new ArrayList<D>(Arrays.asList(target));
l.add(newD);
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
注意:如果我们不能引入新参数,则超级类型令牌将无法解决此问题。如果我错了,请纠正我。
关于java - 如何在Java中实例化通用方法参数的实例?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9689325/