web-dev-qa-db-ja.com

Class.newInstance()が「悪」なのはなぜですか?

Ryan Delucchi 質問 here コメント#3で Tom Hawtin の答え:

class.newInstance()が「悪」なのはなぜですか?

これは、コードサンプルへの応答として:

// Avoid Class.newInstance, for it is evil.
Constructor<? extends Runnable> ctor = runClass.getConstructor();
Runnable doRun = ctor.newInstance();

それで、なぜそれが悪なのでしょうか?

90
Amir Arad

Java APIドキュメントはその理由を説明しています( http://Java.Sun.com/javase/6/docs/api/Java/lang/Class.html#newInstance() ):

このメソッドは、チェック済み例外を含む、nullaryコンストラクターによってスローされた例外を伝播することに注意してください。このメソッドを使用すると、コンパイラによって実行されるコンパイル時の例外チェックを効果的にバイパスできます。 Constructor.newInstanceメソッドは、コンストラクターによってスローされた例外を(チェック済み)InvocationTargetExceptionにラップすることにより、この問題を回避します。

つまり、チェック例外システムを無効にすることができます。

81

もう一つの理由:

最新のIDEでは、クラスの使用法を見つけることができます。リファクタリング中に、あなたとIDEが変更しようとしているクラスを使用しているコードを知っている場合に役立ちます。

コンストラクターを明示的に使用せず、代わりにClass.newInstance()を使用する場合、リファクタリング中にその使用法が見つからないリスクがあり、コンパイル時にこの問題は現れません。

19
alexei.vidmich

Constructor::newInstanceたとえば、最終的にClass::newInstanceはJava-9以降廃止されました。

この非常に単純なクラスがあると仮定します(壊れているかどうかは関係ありません):

static class Foo {
    public Foo() throws IOException {
        throw new IOException();
    }
}

そして、リフレクションを介してそのインスタンスを作成しようとします。最初 Class::newInstance

    Class<Foo> clazz = ...

    try {
        clazz.newInstance();
    } catch (InstantiationException e) {
        // handle 1
    } catch (IllegalAccessException e) {
        // handle 2
    }

これを呼び出すと、IOExceptionがスローされます-問題は、コードがそれを処理せず、handle 1 nor handle 2はキャッチします。

対照的に、Constructorを介して行う場合:

    Constructor<Foo> constructor = null;
    try {
        constructor = clazz.getConstructor();
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    }

    try {
        Foo foo = constructor.newInstance();
    } catch (InstantiationException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        System.out.println("handle 3 called");
        e.printStackTrace();
    }

そのハンドル3が呼び出されるので、それを処理します。

事実上、Class::newInstanceは例外処理をバイパスします-これは本当に望ましくありません。

7
Eugene