タイプパラメータのオブジェクトのインスタンス化


88

次のようなテンプレートクラスがあります。

class MyClass<T>
{
    T field;
    public void myMethod()
    {
       field = new T(); // gives compiler error
    }
}

クラスにTの新しいインスタンスを作成するにはどうすればよいですか?

回答:


85

型消去後、知られているのTは、それがのサブクラスであるということだけですObject。のインスタンスを作成するには、いくつかのファクトリを指定する必要がありますT

1つのアプローチはSupplier<T>:を使用できます。

class MyClass<T> {

  private final Supplier<? extends T> ctor;

  private T field;

  MyClass(Supplier<? extends T> ctor) {
    this.ctor = Objects.requireNonNull(ctor);
  }

  public void myMethod() {
    field = ctor.get();
  }

}

使用法は次のようになります。

MyClass<StringBuilder> it = new MyClass<>(StringBuilder::new);

または、Class<T>オブジェクトを指定してから、リフレクションを使用することもできます。

class MyClass<T> {

  private final Constructor<? extends T> ctor;

  private T field;

  MyClass(Class<? extends T> impl) throws NoSuchMethodException {
    this.ctor = impl.getConstructor();
  }

  public void myMethod() throws Exception {
    field = ctor.newInstance();
  }

}

はどのパッケージにSupplierありますか?`MyClass(Class <?extends T> impl)`は、コンパイルする `throwsNoSuchMethodException`を宣言する必要があります。残念ながら、あなたの答えはJava初心者にはわかりません。
プルキャット2016

@ user927387java.util.function.Supplier
エリクソン

サプライヤー<T>は、価値のあるところならどこでもJava 8、JFTRを必要とします。
Fran Marzoa 2018年

14

もう1つの無反射アプローチは、ハイブリッドビルダー/抽象ファクトリパターンを使用することです。

効果的なJavaでは、Joshua BlochがBuilderパターンを詳細に調べ、一般的なBuilderインターフェースを提唱しています。

public interface Builder<T> {
  public T build();
}

具象ビルダーはこのインターフェースを実装でき、外部クラスは具象ビルダーを使用して必要に応じてビルダーを構成できます。ビルダーは、としてMyClassに渡すことができますBuilder<T>

このパターンを使用するとTTコンストラクターパラメーターがある場合や追加の構成が必要な場合でも、の新しいインスタンスを取得できます。もちろん、BuilderをMyClassに渡す方法が必要になります。MyClassに何も渡せない場合は、BuilderとAbstractFactoryが使用できません。


12

これはあなたが探しているものより重いかもしれませんが、それも機能します。このアプローチを採用する場合は、ファクトリが呼び出されるたびにメソッドに渡すのではなく、ファクトリを構築時にMyClassに挿入する方が理にかなっていることに注意してください。

interface MyFactory<T> 
{
    T newObject();
}

class MyClass<T> 
{
    T field;
    public void myMethod(MyFactory<T> factory)
    {
       field = factory.newObject()
    }
}

1
優れた、無反射のアプローチ。リフレクションは常にオプションであるとは限りません。myMethodはMyFactory <?を受け入れることができるはずです。T>を拡張しますよね?
エリクソン2008年

1
良い呼び出し-タイプTのオブジェクトとTのサブクラスをmyMethod()で作成できるように、ファクトリに制限付きワイルドカードを配置する必要があります。
ダン・ホッジ


-3

クラスclassOfT

        try {
            t = classOfT.newInstance();//new T(); NOTE: type parameter T cannot be instantiated directly
        } catch (Exception e) {
            e.printStackTrace();
        }

2
そのclassOfTクラスはどこで宣言されていますか?
FranMarzoa18年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.