次のコードを変換してジェネリックを使用できますか?
-
09-06-2019 - |
質問
Java 1.5 を使用するようにアプリケーションを変換していて、次の方法を見つけました。
/**
* Compare two Comparables, treat nulls as -infinity.
* @param o1
* @param o2
* @return -1 if o1<o2, 0 if o1==o2, 1 if o1>o2
*/
protected static int nullCompare(Comparable o1, Comparable o2) {
if (o1 == null) {
if (o2 == null) {
return 0;
} else {
return -1;
}
} else if (o2 == null) {
return 1;
} else {
return o1.compareTo(o2);
}
}
理想的には、メソッドで同じタイプの 2 つの Comparable を取得できるようにしたいのですが、これを変換することは可能ですか?
次のようにすればうまくいくと思いました。
protected static <T extends Comparable> int nullCompare(T o1, T o2) {
しかし、IntelliJ の次の行にある「生の型 'java.lang.Comparable' のメンバーとしての 'compareTo(T)' への呼び出しがチェックされていません」という警告を取り除くことができませんでした。
return o1.compareTo(o2);
解決
これを次のように変更します。
protected static <T extends Comparable<T>> int nullCompare(T o1, T o2) {
Comparable 自体がジェネリック型であるため、これが必要になります。
他のヒント
奇妙なケースを次に示します。
static class A {
...
}
static class B extends A implements Comparable<A> {
public int compareTo(A o) {
return ...;
}
}
幸いなことに、上記のようなコードはまれですが、Comparable が T に適用される可能性があると明記されていない限り、nullCompare() は B の比較をサポートしません。 またはそのスーパークラス:
protected static <T extends Comparable<? super T>> int nullCompare(T o1, T o2) {
ほとんどの人は上記の調整から恩恵を受けることはありませんが、エクスポートされたライブラリの API を設計するときに便利になる可能性があります。
編集できないため、回答を投稿する必要があります。
Comparable はジェネリックであるため、ネストされた型パラメータを宣言する必要があります。
protected static <T extends Comparable<? super T>> int nullCompare(T o1, T o2) {
その点に注意してください 同等< ?スーパーT >, 、より柔軟になります。Collections.sort にも同じメソッド定義が表示されます。
public static <T extends Comparable<? super T>> void sort(List<T> list) {
このメソッドを汎用化することが意味があるかどうかはわかりません。現在、このメソッドはあらゆる種類の Comparable で動作します。これを汎用化すると、(まったく同じコードで) 複数回実装する必要があります。共通の祖先を持たない 2 つのオブジェクトを比較できる場合がありますが、汎用バージョンではこれができません。
ジェネリックスを追加しても、コードに安全性はまったく追加されません。安全性の問題は、compareTo の呼び出しで発生します。私が提案したいのは、単に警告を抑制することです。これは実際に何か有益なことについて警告しているわけではありません。
さらに汎用的にするには、2 つの異なるタイプに対して機能させることもできます。=P
/**
* Compare two Comparables, treat nulls as -infinity.
* @param o1
* @param o2
* @return -1 if o1<o2, 0 if o1==o2, 1 if o1>o2
*/
protected static <T> int nullCompare(Comparable<? super T> o1, T o2) {
if (o1 == null) {
if (o2 == null) {
return 0;
} else {
return -1;
}
} else if (o2 == null) {
return 1;
} else {
return o1.compareTo(o2);
}
}