クラス名(動的)を指定して特定のクラスのインスタンスを作成し、そのコンストラクターにパラメーターを渡す方法はありますか?
何かのようなもの:
Object object = createInstance("mypackage.MyClass","MyAttributeValue");
はの"MyAttributeValue"
コンストラクタの引数ですMyClass
。
クラス名(動的)を指定して特定のクラスのインスタンスを作成し、そのコンストラクターにパラメーターを渡す方法はありますか?
何かのようなもの:
Object object = createInstance("mypackage.MyClass","MyAttributeValue");
はの"MyAttributeValue"
コンストラクタの引数ですMyClass
。
回答:
はい、次のようなものです:
Class<?> clazz = Class.forName(className);
Constructor<?> ctor = clazz.getConstructor(String.class);
Object object = ctor.newInstance(new Object[] { ctorArgument });
もちろん、これは単一の文字列パラメーターに対してのみ機能しますが、簡単に変更できます。
クラス名は完全に修飾された名前でなければなりません。つまり、名前空間を含みます。ネストされたクラスの場合は、1ドルを使用する必要があります(コンパイラーが使用するため)。例えば:
package foo;
public class Outer
{
public static class Nested {}
}
そのためのClass
オブジェクトを取得するには、が必要Class.forName("foo.Outer$Nested")
です。
Object[]
引数があるとトリッキーになる可能性があるため、この場合は明示的に配列を作成することを好みます。
を使用Class.forName()
して、Class
目的のクラスのオブジェクトを取得できます。
次に、を使用getConstructor()
して目的のConstructor
オブジェクトを見つけます。
最後に、newInstance()
そのオブジェクトを呼び出して新しいインスタンスを取得します。
Class<?> c = Class.forName("mypackage.MyClass");
Constructor<?> cons = c.getConstructor(String.class);
Object object = cons.newInstance("MyAttributeValue");
リフレクションを使用できます
return Class.forName(className).getConstructor(String.class).newInstance(arg);
Class.forName(className).getConstructor().newInstance();
;)
(つまり)を使用する場合getConstructor(String.lang)
、コンストラクターはパブリックとして宣言する必要があります。それ以外の場合NoSuchMethodException
はスローされます。
非パブリックコンストラクターにアクセスする場合は、代わりに(ie)を使用する必要がありますgetDeclaredConstructor(String.lang)
。
Class<?>
コンストラクタ引数を渡してJavaでオブジェクトを作成する非常に簡単な方法:
ケース1:-
ここに、このMain
クラスの小さなコードがあります。
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class Main {
public static void main(String args[]) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
// Get class name as string.
String myClassName = Base.class.getName();
// Create class of type Base.
Class<?> myClass = Class.forName(myClassName);
// Create constructor call with argument types.
Constructor<?> ctr = myClass.getConstructor(String.class);
// Finally create object of type Base and pass data to constructor.
String arg1 = "My User Data";
Object object = ctr.newInstance(new Object[] { arg1 });
// Type-cast and access the data from class Base.
Base base = (Base)object;
System.out.println(base.data);
}
}
そして、これがBase
クラス構造です:
public class Base {
public String data = null;
public Base()
{
data = "default";
System.out.println("Base()");
}
public Base(String arg1) {
data = arg1;
System.out.println("Base("+arg1+")");
}
}
ケース2:-複数の引数を持つコンストラクターを同様にコーディングし、コンストラクターをコピーできます。たとえば、3つの引数をパラメーターとしてBase
コンストラクターに渡すには、コンストラクターをクラスで作成する必要があり、上記のコードを次のように変更します。
Constructor<?> ctr = myClass.getConstructor(String.class, String.class, String.class);
Object object = ctr.newInstance(new Object[] { "Arg1", "Arg2", "Arg3" });
ここで、Baseクラスは次のようになります。
public class Base {
public Base(String a, String b, String c){
// This constructor need to be created in this case.
}
}
注:- コードで処理する必要があるさまざまな例外を処理することを忘れないでください。
シングルトンパターンに従っているクラスにもかかわらず、誰かがクラスのインスタンスを作成する方法を探しているなら、これを行う方法があります。
// Get Class instance
Class<?> clazz = Class.forName("myPackage.MyClass");
// Get the private constructor.
Constructor<?> cons = clazz.getDeclaredConstructor();
// Since it is private, make it accessible.
cons.setAccessible(true);
// Create new object.
Object obj = cons.newInstance();
これは、プライベートコンストラクターを使用してシングルトンパターンを実装するクラスでのみ機能します。
作成したオブジェクト内のメソッドを呼び出すこともできます。
最初のコンストラクターを呼び出して、作成されたオブジェクトの最初のメソッドを呼び出すことで、オブジェクトを瞬時に作成できます。
Class<?> c = Class.forName("mypackage.MyClass");
Constructor<?> ctor = c.getConstructors()[0];
Object object=ctor.newInstance(new Object[]{"ContstractorArgs"});
c.getDeclaredMethods()[0].invoke(object,Object... MethodArgs);
String
パラメーターとして使用されていることをどのようにして知っていますか?コンストラクターの順序を変更すると少し面倒になる
getConstructor(ClassName.class)
ましだと思います。クラスでコンストラクターの順序が変わっても、手動で位置を見つける必要はありません
別の役立つ答え。getConstructor(params).newInstance(args)を使用するにはどうすればよいですか?
return Class.forName(**complete classname**)
.getConstructor(**here pass parameters passed in constructor**)
.newInstance(**here pass arguments**);
私の場合、私のクラスのコンストラクターはパラメーターとしてWebdriverを取るため、以下のコードで使用します。
return Class.forName("com.page.BillablePage")
.getConstructor(WebDriver.class)
.newInstance(this.driver);
newInstance()
はvarargsメソッドです(と同様GetConstructor()
)Object
。明示的に-arrayを作成する必要はありません。