本文介绍了如何在Java中实例化通用方法参数的实例?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请考虑以下代码:

// ...
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 ;
}

// ..

doIt

中的 ElemType

ElemType.newInstance 不存在,这让我很吃惊。

ElemType.newInstance does not exist, which surprises me.

我已阅读几乎所有常见问题解答,答案和可搜索的内容,但我找不到任何有用的信息。

I've read practically all FAQs, answers and googleable material, but I cannot find anything helpful.

编辑:
是的我知道反射有它的缺点,并不是最终的解决方案,有很多原因。问题不是我应该做什么,而是我该怎么做。

Yes I know reflection has its downsides, and is not the ultimate solution, for numerous reasons. The question is not "should I do it", but "how would I do it".

推荐答案

的通用类型不允许。但你可以实现你想要的像这样:

As mentioned, type erasure of generic types does not allow that. But you can achieve what you want like this:

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);

希望有助于:)

你可能真的想要哈克,并摆脱类参数,并尝试这样:

Note that, one may really want to be hacky and get rid of the class parameter and try this:

 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运行时系统不存储参数化类型(有利于向后兼容性;因此将来可能会更改)。

In fact I thought so before the second edit :) But this gets a "java.lang.ClassCastException: sun.reflect.generics.reflectiveObjects.TypeVariableImpl cannot be cast to java.lang.Class" exception as you mention (I didn't see it because of an overlooked catch statement). In short, Java runtime system does not store the parameterized types (in favor of backwards compatibility; so this may change in the future).

但是,除了上述方法之外,我还可以考虑两件事情。首先,如果BaseClass和DerivedType'D'类实现了clone()方法,你可以从数组中获取一个对象的克隆,然后使用它:

However, other than the mentioned methods, I can think of two more things. First, if both the BaseClass and the DerivedType 'D' class implement clone() method, you can get a clone of an object from the array and then use it:

         D o = target.get(0);

         D oNew = (D)((BaseClass)o).clone();
         target.add(oNew);

多态性将处理其余部分:)

Polymorphism will take care of the rest :)

第二个不是一个真正的解决方案,但如果你想要的是一个新的实例对象的数组参数化的类型,可以使用。类型擦除只发生在参数化类型,但不会发生在基本数组(数组在JVM中被 )。所以如果我们有改变方法的签名的自由和使用数组是确定,那么以下将工作:

The second one is not a real 'solution', but can be used if all you want is a new instance for an array of objects parameterized by type. Type Erasure only happens for parameterized types, but it does not happen for basic arrays (arrays are reified in JVM). So if we have the freedom to change the signature of the method and working with arrays is ok, then the following would work:

    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;
}

注意:如果我们不能引入新的参数。如果我错了,请更正我。

Note: Super type tokens would not work for this problem if we cannot introduce new parameters. Please correct me if I'm wrong.

这篇关于如何在Java中实例化通用方法参数的实例?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-14 05:49