Javaでクラスを名前でインスタンス化する方法はありますか?


102

私は質問として探していました:名前を持つクラスをインスタンス化する方法を説明する文字列名からクラスをインスタンス化します。Javaでそれを行う方法はありますか?パッケージ名とクラス名を取得し、その特定の名前を持つオブジェクトを作成できるようにする必要があります。


クラスインスタンス化すると、結果はオブジェクト(またはインスタンス)になります。
Andreas Dolk 2012年

1
答えはイエスですがそれが良いアイデアどうか尋ねるべきだと思います。大きな力(反射)には大きな責任が伴います。結果を理解して考慮した場合にのみ、それを使用してください。
c1moore

回答:


238

二つの方法:

方法1-引数のないコンストラクターを持つクラスのみ

クラスに引数のないコンストラクターがある場合は、メソッドを使用してClassオブジェクトを取得しClass.forName()newInstance()メソッドを使用してインスタンスを作成できます(ただし、このメソッドはJavaのチェック例外を無効にする可能性があるため、悪と見なされることが多いので注意してください)。

例えば:

Class<?> clazz = Class.forName("java.util.Date");
Object date = clazz.newInstance();

方法2

クラスに引数のないコンストラクタがない場合にも機能する別の安全なアプローチは、クラスオブジェクトをクエリしてそのConstructorオブジェクトを取得しnewInstance()、このオブジェクトのメソッドを呼び出すことです。

Class<?> clazz = Class.forName("com.foo.MyClass");
Constructor<?> constructor = clazz.getConstructor(String.class, Integer.class);
Object instance = constructor.newInstance("stringparam", 42);

どちらの方法も反射と呼ばれます。通常、次のようなさまざまな例外をキャッチする必要があります。

  • JVMがクラスを見つけられない、またはロードできない
  • インスタンス化しようとしているクラスには、適切な種類のコンストラクターがありません
  • コンストラクタ自体が例外をスローしました
  • 起動しようとしているコンストラクタはパブリックではありません
  • セキュリティマネージャがインストールされており、リフレクションの発生を妨げています

こんにちは、からオブジェクトを作成したらnewInstance()、それを自分のオブジェクトにキャストバックできますか?
GMsoF 2014年

@Simonは、セキュリティマネージャーについて詳しく説明/教えてもらえますか?
Ram

分かりません。他のディレクトリにある不明なファイルのクラスにアクセスしたいのですが、パス/ファイルの名前を文字列として持っています。文字列「dir / unkonwn.java」。Class.forName( "dir / unknown")を呼び出すとエラーが発生します。
ジョンktejik

私たちはどのようにキャストすることができますinstanceするにはcom.foo.MyClasscom.foo.MyClassが単なる文字列であることを考えると
Sanket9394

14
MyClass myInstance = (MyClass) Class.forName("MyClass").newInstance();

15
これは、クラスにパラメーターなしのコンストラクターがない(および他のコンストラクターがある)場合、またはパラメーターなしのコンストラクターにアクセスできない場合は機能しないことに言及する価値があります。
Dawood ibnカリーム2012年

3

使用Class.forNameの( "クラスの文字列名")のnewInstance();

Class.forName("A").newInstance();

これにより、Aという名前のクラスが初期化されます。


先頭にパッケージ名を付けても動作しません。:(
trusktr 2013年

3

を使用してインスタンスを作成するためにクラスの完全修飾名を簡単に取得するにClass.forName(...)は、Class.getName()メソッドを使用できます。何かのようなもの:

class ObjectMaker {
    // Constructor, fields, initialization, etc...
    public Object makeObject(Class<?> clazz) {
        Object o = null;

        try {
            o = Class.forName(clazz.getName()).newInstance();
        } catch (ClassNotFoundException e) {
            // There may be other exceptions to throw here, 
            // but I'm writing this from memory.
            e.printStackTrace();
        }

        return o;
    }
}

次に、取得したオブジェクトを、渡したクラスにキャストできますmakeObject(...)

Data d = (Data) objectMaker.makeObject(Data.class);

1
あなたは、単純にすることができないclazz.newInstance()代わりにgetName、その後fromName
user276648 2016

1

Javaリフレクションを使用する

新しいオブジェクトの作成コンストラクターを呼び出すことは、新しいオブジェクトを作成することと同じです(正確には、新しいオブジェクトの作成には、メモリ割り当てとオブジェクト構築の両方が含まれます)。したがって、前の例に最も近いものは次のようになります。

import java.lang.reflect.*;

   public class constructor2 {
      public constructor2()
      {
      }

      public constructor2(int a, int b)
      {
         System.out.println(
           "a = " + a + " b = " + b);
      }

      public static void main(String args[])
      {
         try {
           Class cls = Class.forName("constructor2");
           Class partypes[] = new Class[2];
            partypes[0] = Integer.TYPE;
            partypes[1] = Integer.TYPE;
            Constructor ct 
              = cls.getConstructor(partypes);
            Object arglist[] = new Object[2];
            arglist[0] = new Integer(37);
            arglist[1] = new Integer(47);
            Object retobj = ct.newInstance(arglist);
         }
         catch (Throwable e) {
            System.err.println(e);
         }
      }
   }

これは、指定されたパラメーター型を処理し、それを呼び出すコンストラクターを見つけて、オブジェクトの新しいインスタンスを作成します。このアプローチの価値は、それが純粋に動的であり、コンストラクターの検索と呼び出しがコンパイル時ではなく実行時に行われることです。




0

このようなものはうまくいくはずです...

String name = "Test2";//Name of the class
        Class myClass = Class.forName(name);
        Object o = myClass.newInstance();

0

newInstance()直接使用は、Java 8で非推奨になりましたClass.getDeclaredConstructor(...).newInstance(...)。対応する例外を使用して使用する必要があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.