2

我正在寻找一个很好的模式来执行以下操作:我有一个类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);  
  }
}

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

4

3 回答 3

4

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

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

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

于 2012-04-05T10:00:18.883 回答
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 创建单独的类。

PS我实际上并不认为这种方法比你的更干净:)

于 2012-04-05T08:30:00.753 回答
0

您可以尝试反射,例如

public A produce(Class<A> clazz, B arg) throws IllegalArgumentException, SecurityException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
    return clazz.getConstructor(arg.getClass()).newInstance(arg);
}
于 2012-04-05T08:24:36.503 回答