0

質問:

サブクラスからアクセスされた場合、パラメータ化されたクラスのオブジェクトは非ジェネリックと見なされます。どうすればこれを克服できますか?

詳細:

基本クラスを考えてみましょう:

public class MyBaseClass {
    protected List<Number> numbers = new ArrayList<Number>();

    public MyBaseClass(){
        //...
    }
}

それでは、このクラスを拡張しましょう。

public class MyDerivedClass extends MyBaseClass {

    public void addSomething() {
        numbers.add(25.0f); //Warning about type-safety here
    }
}

派生クラスでは、数値オブジェクトは生の型として表示されます。警告は次のとおりです。

型の安全性: メソッド add(Object) は生の型 List に属します。ジェネリック型 List への参照は、パラメーター化する必要があります。

型パラメーターを自分で追加しようとすると、コンパイル エラーが発生します。

        numbers.<Number>add(25.0f); //Error here

私が見るエラーは次のとおりです。

List 型のメソッド add(Number) はジェネリックではありません。引数でパラメータ化することはできません

ただし、両方のクラスを同じ Java ソース ファイルに配置すると、この問題はなくなります。そもそも予告なし。これは、問題を説明するためのサンプルです。

List私の実際のアプリケーションでは、取得したオブジェクトを適切な型に最初にキャストしなくても、派生クラスの から要素を取得し、それらに対してクラス固有の操作を実行できるようにしたいと考えています。

問題は型消去が原因であると思われますが、それを回避する方法がわかりません。


編集:

Fedora Core 16 で Eclipse 3.7.2 と Oracle JDK 1.6.0_30 を使用しています。コンパイラのコンプライアンスは、デフォルトのコンプライアンス設定で 1.6 に設定されています。前述したように、両方のクラスを同じ .java ファイルに配置すると、警告は表示されません。それらを別のファイルに配置した場合にのみ表示されます。

親クラスのリスト オブジェクトを直接操作するすべてのメソッドを定義することで、これを回避できます。派生クラスからこれを使用します。

しかし、なぜ警告が表示されるのかについてはまだ興味があります。回避策は次のとおりです。

MyBaseClass で:

    protected void addNumberToList(Number num){
        numbers.add(num);
    }

そして派生クラスで:

    public void addSomething() {
        addNumberToList(25.0f);
    }

List同様に、オブジェクトを直接操作するすべての操作を基本クラスに含めることができます。

4

2 に答える 2

3

実際の基本クラスはジェネリックですが、サブクラスは生の型から継承します:

public class MyBaseClass<X> {
    protected List<Number> numbers = new ArrayList<Number>();

    public List<Number> getNumbers() {
        return numbers;
    }
}

public class MyDerivedClass extends MyBaseClass {
    public void addSomething() {
        numbers.add(25.0f);
    }
}

JLS §4.8によると、メンバー アクセスは生の型として扱われます。つまりnumbers、生として扱われるため、警告が表示されます。解決策は、スーパータイプをパラメーター化することです。

public class MyDerivedClass extends MyBaseClass<TypeArgumentsHere>
于 2012-06-21T07:58:46.470 に答える
0

私は Eclipse を使用していますが、あなたのコードは警告やエラーなしで適切に準拠しています。protected/publicただし、インスタンス変数を公開する代わりに、メソッドを提供する必要があると思います。

public class MyBaseClass {
    protected List<Number> numbers = new ArrayList<Number>();

    public List<Number> getNumbers() {
        return numbers;
    }
}

public class MyDerivedClass extends MyBaseClass {

    public void addSomething() {
        getNumbers().add(25.0f);
    }
}
于 2012-06-21T07:17:20.177 に答える