2012-04-05 91 views
2

我正在寻找一个很好的模式来执行以下操作:我有一个类FooBar<A,B>,我知道A具有一个带有单个B参数的构造函数。我想有一个受保护的方法FooBar具有以下特征:Java泛型:使用单个构造函数参数实例化A B

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

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

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

然后让你的类的用户FooBar给你工厂的实例为A型和电流值B.

0

您可以尝试反射,像

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

坎,没有按类型擦除禁止直接将这样的东西写入泛型类? – 2012-04-05 08:26:45

+0

AFAIK无法访问一般参数的类 – 2012-04-05 08:26:53

+0

是的,抱歉。你应该把一个Chuck类转换成一个函数。 – 2012-04-05 08:38:36

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

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

UPDATE: 也有一个办法分裂通用参数沿层次:

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.我实际上并不认为这种方法比你的更干净:)