3

ユーティリティ メソッドを Java 8 に導入したいと考えています。名前付きのメソッドmaxは次のように定義されています。

@SafeVarargs
public static final <E extends Comparable<E>> E max(final E... elements) {
    E result = null; // error
    for(final E e : elements) {
        if(result == null || result.compareTo(e) < 0) {
            result = e;
        }
    }
    return result;
}

Eclipse にエラーが表示されるようになりました。

Null 型の不一致 (型注釈):nullは自由型変数と互換性がありませんE

@Nullableの定義に追加するとエラーが取り除かれると思いresultましたが、明らかにそうではありません。メソッド全体に追加で注釈を付けても@Nullable、エラーは解決しません。

ところで、私は FindBugs の jsr-305.jar を使用しており、Eclipse をjavax.annotation.Nonnullと同様に尊重するように構成しましたjavax.annotation.Nullable。編集:LubuntuでEclipse Luna 4.4.2とOracle JDK 8ビルド1.8.0_25-b17を実行しています。

さて、私の質問です:エラーはどこから来たのですか?注釈とジェネリック型定義の両方の利点を維持しながら、どうすればそれを取り除くことができますか?

編集:デフォルトのEclipseアノテーションが使用されているサンプルプロジェクトを追加したところ、多少機能しているように見えます(result == null結果がその時点でのみnullになる可能性があると誤って推測するため、で警告を生成することを除けば)。したがって、これはデフォルト以外の注釈クラスに関する Eclipse の問題のようです。Eclipse の注釈の独自のコピーを使用して再テストしたNullableところ、上記と同じエラーが発生しました。

4

2 に答える 2

2

エラーはどこから来たのですか?

ドキュメントでこれを見つけました:

制約のない型パラメーターに対応する型変数には、すべての正当な置換で安全性を保証するために、悲観的なチェックが必要です。この型は、null 許容または非 null であると想定することはできません。

class C<T extends Number> {
    int consume(T t) {
        return t.intValue(); // NOT OK since T could be nullable
    }
    T provide() {
        return null;         // NOT OK since T could require nonnull
    }
} 

最後のポイントは最初は驚くかもしれませんが、制約のない型パラメーターは、対応する型変数によって表される型の null 性について何も想定できないことを意味することを理解してください。さらに、null 許容型と非 null 型を積極的にサポートする必要があります。一方、これは、無制限の型変数と互換性のある唯一の型は型変数自体であるという既存の規則を単純に拡張したものです。null 分析のコンテキストでこの状況を説明するために、コンパイラは provide() の戻り値に対して次のエラーを発生させます。

ジェネリック型をインスタンス化するとき、またはジェネリック メソッドを呼び出すときは、型パラメーターによって提示された制約に従う必要があります。

注釈とジェネリック型定義の両方の利点を維持しながら、どうすればそれを取り除くことができますか?

に @Nullable を追加します<E extends Comparable<E>>

@SafeVarargs
public static final  <@Nullable E extends Comparable<E>> E max(final E... elements) {
    E result = null; // no error
    for(final E e : elements) {
        if(result == null || result.compareTo(e) < 0) {
            result = e;
        }
    }
    return result;
}
于 2015-04-01T07:17:21.397 に答える
1

Tja、オプション。varargs 配列が空の場合はどうすればよいでしょうか?

public static final <E extends Comparable<E>> Optional<E> max(final E... elements) {
    Optional<E> result = Optional.empty();
    for(final E e : elements) {
        if(!result.isPresent() || result.get().compareTo(e) < 0) {
            result.set(e);
        }
    }
    return result;
}

または、少なくとも 1 つの引数が必要です。

public static final <E extends Comparable<E>> E max(final E first, final E... elements) {
    E result = first;
    for (final E e : elements) {
        if (/*result != null ||*/ result.compareTo(e) < 0) {
            result = e;
        }
    }
    return result;
}
于 2015-03-31T13:06:47.377 に答える