Java泛型:使用单个构造函数参数B实例化A.

时间:2012-04-05 08:15:21

标签: java generics

我正在寻找一个很好的模式来执行以下操作:我有一个类FooBar<A,B>,我知道A有一个带有B参数的构造函数。我希望FooBar中的受保护方法具有以下签名:

protected A chuckNorris42(B b); // intent: return new A(b)

当然上面提到的“意图”是不可编辑的。作为一种解决方法,我使这个方法变得抽象,并且在我使用具体类实例化FooBar时,我实现了chuckNorris42内联:

FooBar<Chuck, Norris> = new FooBar<Chuck, Norris>() {
  protected Chuck chuckNorris42(Norris norris) {
    return new Chuck(norris);  
  }
}

它有效,但我想知道是否有更好或更清洁的方法来实现同样的事情所以我决定在这里提出问题。

3 个答案:

答案 0 :(得分:4)

关键是,你不知道A的任何实际实例都有这样的构造函数,Java类型系统不够强大,无法强制执行此操作。因此,没有干净的通用内置方法来调用静态不知道的类的构造函数。你必须像在其他答案中一样使用反射,但是如果A突然用一个不可实例化的类型实例化(例如,A可能是一个抽象类!),或者没有适当的构造函数。如果你想避免这种情况,你可以使用工厂:

interface Factory<A, B> {
  A createInstance(B b);
}

然后让您的班级FooBar的用户为您提供该工厂的实例,以获取A和B类型的当前值。

答案 1 :(得分:2)

我不确定它更好更清洁,但你可以尝试这样的事情:

public class FooBar<A,B> {
private Class<A> aClass;
public FooBar(Class<A> aClass) {
    this.aClass = aClass;
}

protected A chuckNorris42(B b) throws NoSuchMethodException, InstantiationException,IllegalAccessException,InvocationTargetException{
    return aClass.getConstructor(b.getClass()).newInstance(b);
}
}

没有办法获得泛型参数的类。因此,实例化泛型参数类的对象的方法之一是在构造函数中传递类。

<强>更新 还有一种方法可以在层次结构中拆分泛型参数:

public abstract class Foobar<A,B> {
   protected abstract A chuckNorris(B b);
}

public class FooBarChuck<B> extends Foobar<Chuck<B>,B>{

   @Override
  protected Chuck<B> chuckNorris(B b) {
      return new Chuck<B>(b);
  }
}
public class Chuck<B> {
  public Chuck(B b) {
    //something here
  }
}

然后你不必为所有B类重新实现这个方法,但你仍然需要为每个Chuck创建单独的类。

P.S。我实际上并不认为这种方法比你的方法更清洁:)

答案 2 :(得分:0)

您可以尝试反思,例如

public A produce(Class<A> clazz, B arg) throws IllegalArgumentException, SecurityException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
    return clazz.getConstructor(arg.getClass()).newInstance(arg);
}