2012-04-05 5 views
2

私はクラスを持っています:FooBar<A,B>クラスがあり、AにはBという単一のコンストラクタがあることがわかります。上記の「意図」は、コンパイルではありません。もちろん、Javaジェネリック:単一のコンストラクタ引数でAをインスタンス化するB

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

:私は、次のシグネチャでFooBarで保護されたメソッドを持っているしたいと思います。回避策として、私は、このメソッドの抽象を作り、私は具体的なクラスでFooBarをインスタンス化の時点で私はchuckNorris42インライン実装:それは作品

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

を、私は同じことを達成するために、よりよいか、きれいな方法があればと思いました私はここで質問をすることにしました。

答えて

4

ポイントは、Aの実際のインスタンスは、このようなコンストラクタを持っていることを知らない、Java型システムはちょうどこれを強制する。したがって、静的に知らないクラスのコンストラクタを呼び出すためのクリーンな汎用組み込みの方法はありません。あなたは他の答えのようにリフレクションを使用する必要がありますが、Aはインスタンス化できないタイプ(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

ハム、doesnの現在の値に対するそのファクトリのインスタンスを与えてみましょうこのようなものをジェネリッククラスに直接書くのを禁止しますか? –

+0

AFAIK一般的な引数のクラスにアクセスする方法はありません –

+0

ええ、申し訳ありません。 Class of Chuckを関数に渡す必要があります。 –

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

に方法はありじゃないんですジェネリック引数のクラスを取得します。したがって、汎用引数クラスのオブジェクトをインスタンス化するメソッドの1つは、クラスをコンストラクターに渡すことです。

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クラスのこのメソッドを再実装する必要はありませんが、あなたはまだする必要があります:への道は、下の階層ジェネリック引数を分割もあり チャックごとに別のクラスを作成します。

P.私は実際には、このメソッドはあなたよりもはるかにきれいだとは思わない:)

関連する問題