3

ジェネリックスを使用していくつかのコードを記述しましたが、理解できなかった次の状況に陥りました。

インターフェイスIpRangeと次のクラスがあります。

public class Scope<IpRange<T extends IP>> {
     List<IpRange<T>> rangesList;
     public List<IpRange<T>> getRangesList() {return rangesList;}
}

今、私が次のように書いた場合、いくつかのテストクラスから:

Scope<Ipv4> myScope = new Scope<Ipv4>(); 
scope.getRangesList().get(0)

IpRange型のオブジェクトを取得していますが、raw型を使用してこれを実行している場合:

Scope myScope = new Scope();
scope.getRangesList().get(0)

Objectを取得していますが、明示的にRangeにキャストしない限り、ipRangeメソッドを使用できません。

生のタイプを使用したので、コンパイラはリストアイテムの実際のタイプを知る方法がありませんが、この場合List<T>は常にIpRangeタイプになるので、なぜObjectを取得しないのですか? ?

問題は、スコープを作成するときに、実際の範囲タイプが必ずしもわからないということです。このコンストラクターについて考えてみます。publicScope(String rangeStringList); 私が知っている限りでは、文字列は「16.59.60.80」または「fe80 :: 10d9:159:f:fffa%」である可能性があります。しかし、私が知っているのは、IpRangeオブジェクトをコンパイラーに渡したということです。これがipv4でもipv6でも、このインターフェイスを使用できると期待しています。また、行タイプを使用した場合でも、コンパイラはこれがipRangeであることを確実に認識できるため、Javaがこの方法を選択したのはなぜかと思います。

4

3 に答える 3

2

生の型を使用すると、すべてのジェネリック型情報が取り除かれることを人々は指摘し、これは下位互換性に関係しているとほのめかしました。これは説明なしでは満足できないかもしれないと思うので、あなたのようなコードでそのような問題がどのように発生するかを説明しようと思います.

まず、あなたが書いたコードが古いライブラリの一部であり、ジェネリックを追加してライブラリをアップグレードしている最中だと想像してください。おそらくこれは人気のあるライブラリであり、多くの人が古いコードを使用しています。

ライブラリのクラスを使用して、誰かが次のようなことをした可能性があります。

private void someMethod(Scope scope, Object object) {
  scope.getRangesList().add(object);
}

これを見ると、Object が IpRange 型ではない可能性があることがわかりますが、これはプライベート メソッドであるため、someMethod を呼び出すメソッドによって型チェックが効果的に実行されると仮定しましょう。これは良いコードではないかもしれませんが、ジェネリックがなければコンパイルされ、問題なく動作する可能性があります。

これを書いた人が、いくつかの新機能や未実現のバグ修正のためにライブラリの新しいバージョンにアップグレードしたと想像してください。これに伴い、ジェネリック クラスでより多くのタイプ セーフにアクセスできるようになりました。ただし、生の型を使用した上記のコードの抽出のようなレガシーが多すぎるため、使用したくない場合があります。

あなたが効果的に示唆しているのは、「スコープ」が生の型であっても、getRangesList() から返されるリストは常に List<IpRange<? 型でなければならないということです。IP>> を拡張しているため、コンパイラはこれに気付くはずです。

ただし、この場合、オブジェクトをリストに追加する上記のレガシー コードは、編集しないとコンパイルできなくなります。これは、生の型の利用可能なすべてのジェネリック型情報を無視せずに下位互換性を破る 1 つの方法です。

于 2012-11-22T11:24:28.213 に答える
1

はい、未加工の型を使用すると、そのメソッドの残りの部分ですべてのジェネリックが「オフ」になり、すべてのジェネリック型が代わりに未加工の型になります。

于 2012-11-22T01:02:40.257 に答える
0

生の型を使用すると、インスタンスで呼び出された場合の静的メソッドを含め、すべてのジェネリック型情報がクラスから削除されます。

これが行われた理由は、Java 1.4 との下位互換性のためです。

于 2012-11-22T01:38:32.663 に答える