27

javadocは次のようにVoid述べています。

Voidクラスは、Javaキーワードvoidを表すClassオブジェクトへの参照を保持するためのインスタンス化できないプレースホルダークラスです。

しかし、コンストラクターは単純です。

private Void() {}

このコードは:をインスタンス化しますVoid

Constructor<Void> c = Void.class.getDeclaredConstructor();
c.setAccessible(true);
Void v = c.newInstance(); // Hello sailor

したがって、インスタンス化できないわけVoidではありません。

Void本当にインスタンス化できないようにする方法はあったでしょうか?

4

3 に答える 3

31

ほとんどのユースケースでは、例外をスローするだけで「十分」であるという Rohit の意見は正しかったと言えます。ただし、 sun.misc.Unsafe を使用して、それをバイパスすることもできるようです:

public native Object allocateInstance(Class cls) が InstantiationException をスローする

インスタンスを割り当てますが、コンストラクターは実行しません。クラスが初期化されていない場合は、初期化します。

(これが機能することを実際にテストしていないことに注意してください)

于 2012-12-27T19:53:11.363 に答える
30

コンストラクターを非公開にし、外部からアクセスできる他のコンストラクターを持たないようにすると、クラスはインスタンス化できなくなります。

ただし、 を使用してアクセスすることは避けられませんReflection API。リフレクションを使用すると、通常は許可されていないことができます。

ただし、クラスをインスタンス化できないようにしたい場合は、リフレクションを使用しても、コンストラクターからUnchecked Exceptionを実行できます。throw

private MyClass() {
    throw UnsupportedOperationException("Can't instantiate class");
}

その場合、メソッドを使用してインスタンスを作成すると、@Alex のコメントで引用されているように、Constructor#newInstance()がスローされます。InvocationTargetException

Constructor#newInstance()これは、スローされる例外のリストを宣言するメソッドのドキュメントです。そのうちの1つはInvocationTargetExceptionであり、それは次のように述べています: -

throws:
InvocationTargetException - 基になるコンストラクターが例外をスローした場合。

于 2012-12-27T19:27:49.210 に答える
11

Reflection API は、フィールドを変更できるように、このようなあらゆる種類の「ルール」を破りfinalます。Java の厳格で厳格な規則を破ることができるという事実について多くの不満がありますが、それはその通りです。

Reflection (または以下に投稿された @StevenSchlansker のクレイジーなUnsafeAPI) がなければ、インスタンス化することはできません。ただし、リフレクションが許可されている限り、これらの回避策は存在します。

Oracle 独自の Reflection チュートリアルでは、メリットとデメリットがリストされています。どちらが大きいかはあなた次第です。

また、次の質問も参照してください

于 2012-12-27T19:25:08.763 に答える