これはコンパイルされません、どんな提案もありがたいです。
...
List<Object> list = getList();
return (List<Customer>) list;
コンパイラは言う:キャストすることはできませんList<Object>
にList<Customer>
これはコンパイルされません、どんな提案もありがたいです。
...
List<Object> list = getList();
return (List<Customer>) list;
コンパイラは言う:キャストすることはできませんList<Object>
にList<Customer>
回答:
オブジェクトを最初にObjectにアップキャストすることで、いつでもオブジェクトを任意の型にキャストできます。あなたの場合:
(List<Customer>)(Object)list;
実行時には、リストにCustomerオブジェクトのみが含まれていることを確認する必要があります。
批評家は、そのようなキャストはコードに問題があることを示していると言います。それを避けるために型宣言を微調整できるはずです。しかし、Javaジェネリックは複雑すぎて、完璧ではありません。ランタイムタイプをよく知っていて、実行しようとしていることが安全であるとわかっていても、コンパイラーを満足させるための素晴らしい解決策があるかどうかわからない場合があります。その場合は、必要に応じて粗鋳造を行うだけで、家に帰ることができます。
@SuppressWarnings("unchecked")
です。to (List)
ではなくto にアップキャストすることもできます(Object)
。
これは、顧客はオブジェクトですが、顧客のリストはオブジェクトのリストではないためです。ある場合は、顧客のリストに任意のオブジェクトを配置できます。
.Cast<T>()
と呼ばれるものを.OfType<T>()
。前者は各要素に対してキャストを実行し(必要な例外をスロー)、後者はキャストできない要素を除外します(使用シナリオに応じて選択します)。
instanceof
Customer でない場合はどうなりますか?
Java 8 ストリームの場合:
時々ブルートフォースキャスティングは問題ありません。
List<MyClass> mythings = (List<MyClass>) (Object) objects
しかし、これはより用途の広いソリューションです:
List<Object> objects = Arrays.asList("String1", "String2");
List<String> strings = objects.stream()
.map(element->(String) element)
.collect(Collectors.toList());
たくさんの利点がありますが、1つは、何が含まれているかわからない場合に、リストをよりエレガントにキャストできることです。
objects.stream()
.filter(element->element instanceof String)
.map(element->(String)element)
.collect(Collectors.toList());
FluentIterable
うまくいきました。
私はJavaプログラマではありませんが、.NETおよびC#では、この機能は反変または共分散と呼ばれています。それらは.NET 4.0の新機能であるため、まだ詳しく説明していません。ベータ版であるため使用していません。2つの用語のどちらが問題を説明しているかはわかりませんが、これに関する技術的な問題。
あなたがキャストを許可されていたとしましょう。注:キャストと言いますが、それはあなたが言ったことですが、可能な2つの操作、キャストと変換があります。
変換とは、新しいリストオブジェクトを取得することを意味しますが、キャストとは、あるオブジェクトを別のタイプとして一時的に処理することを意味します。
これが問題です。
以下が許可された場合はどうなりますか(キャストの前は、オブジェクトのリストには実際にはCustomerオブジェクトのみが含まれていると想定しています。それ以外の場合、この仮想バージョンのjavaでもキャストは機能しません)。
List<Object> list = getList();
List<Customer> customers = (List<Customer>)list;
list.Insert(0, new someOtherObjectNotACustomer());
Customer c = customers[0];
この場合、これは顧客ではないオブジェクトを顧客として処理しようとし、リスト内のフォームまたは割り当てから、ある時点でランタイムエラーが発生します。
ただし、ジェネリックスは、コレクションなどのタイプセーフなデータ型を提供することになっています。また、「保証された」という言葉を投げかけたいので、この種のキャストは、以下の問題があるため、許可されていません。
.NET 4.0では(私は知っています、あなたの質問はJavaについてでした)、これはいくつかの非常に特殊なケースで許可されますが、コンパイラはあなたが行う操作が安全であることを保証できますが、一般的な意味でこのタイプのキャストは許可されている。同じことがJavaにも当てはまりますが、Java言語に共分散および反変を導入する計画についてはよくわかりません。
うまくいけば、私よりもJavaの知識が豊富な人に、Javaの将来や実装の詳細を教えてもらえますか。
あなたは理由ができないList<Object>
とList<Customer>
同じ継承ツリーではありません。
List<Customer>
クラスに新しいコンストラクターを追加してa を受け取りList<Object>
、リストを繰り返し処理してそれぞれObject
をaにキャストし、Customer
それをコレクションに追加します。呼び出し元List<Object>
がでないものを含んでいる場合、無効なキャスト例外が発生する可能性があることに注意してくださいCustomer
。
ジェネリックリストのポイントは、リストを特定のタイプに制限することです。何かを含むことができるリスト(注文、製品など)を取得して、顧客のみを取得できるリストに絞り込みます。
あなたの最善の策は、新しいを作成しList<Customer>
、を反復処理し、List<Object>
各項目を新しいリストに追加して、それを返すことです。
他の人が指摘したように、a List<Object>
はでないため、それらを保存してキャストすることはできませんList<Customer>
。あなたができることは、その場で型チェックを行うリストのビューを定義することです。次のようなGoogleコレクションを使用します。
return Lists.transform(list, new Function<Object, Customer>() {
public Customer apply(Object from) {
if (from instanceof Customer) {
return (Customer)from;
}
return null; // or throw an exception, or do something else that makes sense.
}
});
上記のBozhoと同様。この方法を使用して、ここでいくつかの回避策を実行できます(私自身はそれが好きではありません)。
public <T> List<T> convert(List list, T t){
return list;
}
はい。リストを要求されたジェネリック型にキャストします。
上記のケースでは、次のようなコードを実行できます。
List<Object> list = getList();
return convert(list, new Customer());
リストの処理方法によっては、それをにキャストする必要がない場合もありますList<Customer>
。Customer
リストにオブジェクトを追加するだけの場合は、次のように宣言できます。
...
List<Object> list = getList();
return (List<? super Customer>) list;
これは合法です(まあ、合法だけでなく、正しい -リストは「顧客へのスーパータイプ」です)。そして、リストにオブジェクトを追加するだけのメソッドにそれを渡す場合は、上記のこれには一般的な境界で十分です。
一方、リストからオブジェクトを取得して、Customersとして強く入力したい場合は、運が悪いため、当然です。このリストはList<Object>
コンテンツであることを保証するものではないため、取得時に独自のキャストを提供する必要があります。(または、本当に、絶対に、リストCustomers
には他の回答のいずれかからのダブルキャストのみが含まれ、使用されることを二重に確認してください。場合)。
大まかに言って、メソッドを書くときに許容できる最も広い一般的な境界を検討することは常に良いことです。リストから読み取るだけの場合List<? extends T>
はList<T>
、たとえばの代わりに使用します。これにより、呼び出し元が渡すことができる引数の範囲がはるかに広くなり、呼び出し元と同様の回避可能な問題が発生する可能性が低くなります。ここで持っている。