次のようなテンプレートクラスがあります。
class MyClass<T>
{
T field;
public void myMethod()
{
field = new T(); // gives compiler error
}
}
クラスにTの新しいインスタンスを作成するにはどうすればよいですか?
次のようなテンプレートクラスがあります。
class MyClass<T>
{
T field;
public void myMethod()
{
field = new T(); // gives compiler error
}
}
クラスにTの新しいインスタンスを作成するにはどうすればよいですか?
回答:
型消去後、知られているの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();
}
}
java.util.function.Supplier
もう1つの無反射アプローチは、ハイブリッドビルダー/抽象ファクトリパターンを使用することです。
効果的なJavaでは、Joshua BlochがBuilderパターンを詳細に調べ、一般的なBuilderインターフェースを提唱しています。
public interface Builder<T> {
public T build();
}
具象ビルダーはこのインターフェースを実装でき、外部クラスは具象ビルダーを使用して必要に応じてビルダーを構成できます。ビルダーは、としてMyClassに渡すことができますBuilder<T>
。
このパターンを使用するとT
、T
コンストラクターパラメーターがある場合や追加の構成が必要な場合でも、の新しいインスタンスを取得できます。もちろん、BuilderをMyClassに渡す方法が必要になります。MyClassに何も渡せない場合は、BuilderとAbstractFactoryが使用できません。
これはあなたが探しているものより重いかもしれませんが、それも機能します。このアプローチを採用する場合は、ファクトリが呼び出されるたびにメソッドに渡すのではなく、ファクトリを構築時にMyClassに挿入する方が理にかなっていることに注意してください。
interface MyFactory<T>
{
T newObject();
}
class MyClass<T>
{
T field;
public void myMethod(MyFactory<T> factory)
{
field = factory.newObject()
}
}
サブクラス化する場合は、消去も回避できます。http://www.artima.com/weblogs/viewpost.jsp? thread = 208860を確認して ください。
クラスclassOfT
try {
t = classOfT.newInstance();//new T(); NOTE: type parameter T cannot be instantiated directly
} catch (Exception e) {
e.printStackTrace();
}
Supplier
ありますか?`MyClass(Class <?extends T> impl)`は、コンパイルする `throwsNoSuchMethodException`を宣言する必要があります。残念ながら、あなたの答えはJava初心者にはわかりません。