私はView.findViewById(int id)
の代わりに方法を書いた、しかし、私は警告だ: Javaのジェネリックメソッドの警告「未検査キャスト」
をこの方法でも問題はありますか?またはそれを避ける方法?
私はView.findViewById(int id)
の代わりに方法を書いた、しかし、私は警告だ: Javaのジェネリックメソッドの警告「未検査キャスト」
をこの方法でも問題はありますか?またはそれを避ける方法?
私はこれが警告の理由だと考えています。Javaではダウンキャストが可能です。すなわち、X型のオブジェクトをXのサブクラスにキャストします。ただし、実行時にチェックが必要です。たとえば:
Object x1 = <... something that returns an object that may be a String ...>;
String x2 = (String)x1;
キャストがString
としてx1
を扱うしようとします。しかし、x1
は任意のObject
になります。 String
である場合とそうでない場合があります。キャストはx1
が実際にString
の場合にのみ有効です。そうでなければ、実行時にClassCastException
が得られます。
T
のサブクラスは、View
のサブクラスであり、これは通常、実行時に同じ種類のチェックが実行されることを意味します。ただし、タイプ消去のため、コードのこの時点でプログラムは実際にT
のクラスに関する情報を持っていません。つまり、チェックを実行できません。したがって、チェックされていない操作を使用しているプログラムについての警告が表示されます。このメソッドが返すとき、返されたオブジェクトは実際にはクラスT
のインスタンスになることは保証できません。
いくつかのテストケースを試したところ、が汎用メソッドをと呼ぶという発言でよくチェックが行われました。 View2
がView
に拡張されていて、を返すようにfind
を使用するとします。その後:findViewById
で見つかったオブジェクトが本当にView2
ない
View2 v = YourClass.<View2>find(x, id);
場合は、ClassCastException
を取得します。しかし、
findViewById
が別のビューを返すとします。私のテストに基づいて、型パラメータがView2
であっても、これは例外をスローしません。これはView
に割り当てられます。結果が他のビューであれば正常に動作し、View2
のチェックは行われません。
String s = YourClass.<View2>find(x, id).toString();
findViewById
が別のビューを返すとします。私はこれを試してみたとき、他のビューにもtoString()
(すべてObject
のようなもの)があるので、例外をスローしないと思った。しかし、これはClassCastException
を投げた。
私はそれを修正するための良い方法があるかどうかわかりません。一つの可能性はT
のクラスを表すためにfind
に三番目のパラメータを追加し、そのcast
メソッドを使用することです:
public static <T extends View> T find(View view, int id, Class<T> theClass) {
return theClass.cast(view.findViewById(id));
}
View v = YourClass.find(x, id, View2.class);
からfindViewById
が間違ったクラスを返すかどうかはcast()
メソッドから例外がスローされます。ただし、コールから明示的なジェネリック型パラメータを削除することは可能ですが、すべての用途に第3のパラメータを追加することは魅力的ではないかもしれません。
これは、警告を無視して、警告が表示されないようにするために使用するといいと思うのですが、findViewById
の場合に例外をスローするのではなく、プログラムが続行する可能性がある間違った種類のビューを返します。
(免責事項:私のテストはJava 8を使用して実行されました。Java 7では有効ではないものは使用しませんでしたが、まだAndroid 7が完全にJava 7を実装していない場合、間違っている可能性があります)