Java 1.4のリストでジェネリックを使用することは可能ですか?
質問
Java 1.4を使用する必要があり、ArrayList構造を使用しています。今、私はいくつかの再因子を行う必要があり、ジェネリックを使用できれば役立ちます。現在、このようなコードがあります
ArrayList rows = new ArrayList();
これは簡単なArrayListです。しかし、今では「行」変数はより複雑になり、「行」クラスを定義する必要があります。私は今、J2SE1.5であなたが見ているようなことをしたいです
ArrayList<Row> rows = new ArrayList();
Googleを介したトロールは、サードパーティのソリューションを洗練した使用なしには回答を公開しません。サードパーティのソリューション/オープンソースプロジェクトを使用せずに、(可能であれば)、私のコードはどのように変更する必要がありますか?
解決
ジェネリックはJDK 1.5に導入されました。したがって、1.4でそれらを使用することはできません。ただし、JDK 1.5コンパイラを使用することができるかもしれませんが、クラスで1.4をターゲットにします -target 1.4
維持中のJavacオプション -source 1.5
ソースが1.5互換であることを示すオプション。この場合、結果クラスに影響を与えないはずであるため、ジェネリックを使用できます。
他のヒント
Genericsは、コレクションを扱うときにJava 1.4以前の「ナイーブキャスト」とみなす問題に対処する傾向があります。 Java 1.5+で、あなたが配置したライン:
ArrayList<Row> rows = new ArrayList();
警告を発します、適切な一般的なコードは
ArrayList<Row> rows = new ArrayList<Row>();
これにより、コンパイラに、配列リストオブジェクトには行タイプのみが含まれている必要があることがわかります。
ただし、Java 1.5は、その構文を含むのではなく、以前のコードを含む膨大なライブラリセットとともに後方互換性があります。
ArrayList rows = new ArrayList();
ジェネリックは明らかにこれらの古いライブラリでは機能しません - したがって、ジェネリックは 時間をまとめます オプション-1.5および1.4クラスは、オブジェクトタイプを処理するArrayList実装であるため、効果的に同等です(後で追加される内部リファクタリング/新しいメソッドを除く)。
1.5コードは、直接キャストに追加されます。
1.4コードでは、配列を繰り返したいとします。これを行うための素朴なキャスト方法は次のとおりです。
for(Iterator rowIterator = rows.iterator(); rowIterator.hasNext(); ) {
Row row = (Row) rowIterator.next();
// Do something with the row.
}
Java 1.5のコードは、ナイーブキャストバージョンとまったく同じです。コンパイラにそれを伝えているという事実が必要です は 行とあなたのためにそのコードを行います。したがって、構文砂糖の利点はより良くなります(これは各ループ構文に新しいものを使用しますが、上記のループと同じコードを生成します):
for(Row row : rows) {
// Do something with the row
}
したがって、行のみを含む配列リストを使用する場合でも、まだできます。しかし、コンパイラをに取得する方法はありません 小切手 ArrayListにはすべての行のみが含まれていること(ただし、コンパイラがこのチェックを提供している場合でも、 まだ可能です 他のタイプのオブジェクトを含むアレイリストを送信するには、アレイリストが実際にオブジェクトタイプを実際に処理し、ジェネリックが実行時に消去されるため、残っているのはもう見えない素朴なキャストコードだけです。 。
NONVERIVEバリアントは、各インスタンスをチェックし、有益なメッセージでClassCastExceptionを自分で投げることです(プログラムにデフォルトのメッセージで1つを投げるのではなく):
for(Iterator rowIterator = rows.iterator(); rowIterator.hasNext(); ) {
Object shouldBeRow = rowIterator.next();
if(!(shouldBeRow instanceof Row)) {
throw new ClassCastException("The object " + shouldBeRow + " is not an instance of Row - only Rows should be present in the list!");
}
Row row = (Row) shouldBeRow;
// Do something with the row.
}
ただし、一般的に誰もこれを行いません - 良いドキュメントは、この問題を発信者に提供する負担をかけるため、JVMがClassCastExceptionを投げるだけであるためです。
はい、できます。 1.5コンパイラを使用して使用します
javac -target jsr14 ............
これにより、Java 1.4クラスが生成されますが、ジェネリックが許可されます。
このスイッチは、非バイトコードに見える1.5機能にのみ使用できます。たとえば、1.5で導入された新しいメソッドを使用することはできません。しかし、ジェネリックはバイトコードに実際に存在していないため、問題ありません。
いいえ、JDK 1.4でそれらを使用することはできません。それらはJDK1.5で導入されました
あなたがしなければならないのはそれらをキャストすることだけです。これは、「間違った」タイプをリストに入れた場合、ランタイム例外に値する可能性があります。
Row arow = (Row) rows.get(0);
for ($i=0; i<rows.size(); $i++){
Row element = (Row) rows.get($i);
element.printCells();
(...)
}