18

コンパイル時エラー:ジェネリック クラスは java.lang.Throwable をサブクラス化できない可能性があります

public class TestGenericClass<E> extends Exception {

/*Above line will give compile error, the generic class TestGenericClass<E> may 
  not subclass java.lang.Throwable*/

    public TestGenericClass(String msg) {
        super(msg);
    }
}

上記のコンパイル時エラーは、以下の§ jls-8.1.2に記載されている理由によるもので、この質問で説明されています。

ジェネリック クラスが Throwable (§11.1.1) の直接または間接のサブクラスである場合、コンパイル時エラーになります。

Java 仮想マシンのキャッチ メカニズムは非ジェネリック クラスでのみ機能するため、この制限が必要です。

質問:

  • java.lang.Throwableのサブクラスがジェネリック クラスにならないことはどのように制限されますか?

  • または、より一般的な質問は、どのクラスのサブクラスもジェネリックにできないことを制限する方法ですか?

4

3 に答える 3

10

java.lang.Throwable のサブクラスがジェネリック クラスにならないように制限するにはどうすればよいですか?

これは、コンパイラ自体に特別なケースを書き込むという決定でした。その理由は、この質問で詳しく説明されています。基本的に、これは型がreifiableであることに関係しています。この用語については、こちらで読むことができます。つまり、コンパイル時に型が完全に利用可能である場合、その型は具体化可能です。たとえば、ジェネリック型は型消去によって型が削除されるため、具体化できません。catchブロックに表示されるオブジェクトは、具体化可能である必要があります。

または、より一般的な質問、クラスのサブクラスがジェネリックにならないことを制限する方法は?

さて、いくつかのオプションがあります..

現在、Java の通常の範囲内でこれを行うオプションはありません。final汎用性がサブクラスに適用されるのを防ぐような実装はありません。コメントで説明されているように、これに最も近いのは、コンパイラを拡張し、クラス専用のルールを追加することです。このソリューションは私の背筋を震えさせます。かわす。つまり、あなたのコードはあなたのバージョンの Java でのみ動作し、あなたのコードを使用したい人は同じバージョンをインストールする必要があります。

明らかに、他のオプションは拡張することThrowableですが、これは本当に良い考えではありません。クラスにたくさんの機能を追加し、決して使用しない多くの新しいメソッドをクラスのインターフェースに追加します。OOP の観点からは、この機能を利用するために、クラスの整合性を犠牲にしています。

于 2014-05-03T21:22:41.903 に答える
1

実行時までエラーを遅らせる場合は、スーパークラス コンストラクターでリフレクションを使用して、サブクラスが型パラメーターを宣言しているかどうかを確認できます。

public class Example {
    public static class ProhibitsGenericSubclasses {
        public ProhibitsGenericSubclasses() {
            if (getClass().getTypeParameters().length > 0)
                throw new AssertionError("ProhibitsGenericSubclasses prohibits generic subclasses (see docs)");
        }
    }

    public static class NonGenericSubclass extends ProhibitsGenericSubclasses {}
    public static class GenericSubclass<T> extends ProhibitsGenericSubclasses {}

    public static void main(String[] args) {
        System.out.println(new NonGenericSubclass());
        System.out.println(new GenericSubclass<Object>());
    }
}

このコードは印刷します

Example$NonGenericSubclass@15db9742
Exception in thread "main" java.lang.AssertionError: ProhibitsGenericSubclasses prohibits generic subclasses (see docs)
    at Example$ProhibitsGenericSubclasses.<init>(Example.java:12)
    at Example$GenericSubclass.<init>(Example.java:17)
    at Example.main(Example.java:21)

最も派生したクラスだけでなく、階層内のすべてのクラスの型パラメーターを禁止する場合は、を使用して階層を上る必要がありますClass#getSuperclass()

于 2014-05-08T06:01:05.670 に答える