0

次のジェネリック クラスでは、行 r=g にコンパイル エラーがあります: タイプの不一致: GenericTest1<Integer> から GenericTest1<Number> に変換できません。

public class GenericTest1<T> {
    private T t;

    public GenericTest1(T t) {
        this.t = t;
    }

    public void set(T t) {
        this.t = t;
    }

    public T get() {
        return t;
    }

    public static void main(String[] args) {
        GenericTest1<Integer> g = new GenericTest1<>(6);
        GenericTest1<Number> r = g; <==here
    }
}
4

5 に答える 5

1

ここでの誤解は、GenericTest1<Number>が のスーパークラスであるというものですGenericTest1<Integer>。そうではないので、各メンバーを個別にキャストする必要があります。

于 2012-11-14T06:43:13.783 に答える
1

ジェネリックを使用したプログラミングに関しては、よくある誤解です。ここで 2 つの具象型GenericTest1<Integer>GenericTest1<Number>は関係ありません。唯一の共通部分は、両方が のサブクラスであることObjectです。

于 2012-11-14T06:43:47.357 に答える
1

2 つのクラス、GenericTest<Number> および GenericTest<Integer> は代入互換性がありません。それらをキャストすることさえできません。ただし、オブジェクトをコピーしても構わない場合は、次の操作を実行できます。

クラスにコピー コンストラクターを追加します。

public GenericTest1(GenericTest1<? extends T> other) {
    this.t = other.t;
}

次に、オブジェクトをコピーします。

public static void main(String[] args) {
    GenericTest1<Integer> g = new GenericTest1<>(6);
    GenericTest1<Number> r = new GenericTest1<Number>(g);
}
于 2012-11-14T06:45:37.790 に答える
0

まず、クラスで許容される型を制限し、フィールドをNumber他のフィールドと比較するメソッドを導入し、次のGenericNumberようなジェネリック クラスを定義します。

public class GenericNumber<T extends Number> {
    private T number;
    public T getNumber() {
        return number;
    }
    public void setNumber(T number) {
        this.number = number;
    }
    public void setNumber(T number) {
        this.number = number;
    }
    //constructors
    public int compareTo(Number n) throws Exception {
        if((number == null) || (n == null))
            throw new Exception("Can't compare null values");
        else if(number.doubleValue() > n.doubleValue)
            return 1;
        else if(number.doubleValue() == n.doubleValue)
            return 0;
        else
            return 1;
    }
    public int compareTo(GenericNumber n) throws Exception {
        if(n == null)
            throw new Exception("Can't compare null values");
        return compateTo(n.getNumber());
    }
}

このアプローチでは、インスタンスの等価性のテストは、オブジェクトを使用して次の条件に変換されます: (r.compareTo(g) == 0).

このタイプの Java フレーバーの比較クラス メソッドを使用したくない場合は、もちろん、フィールドを型キャストし、=演算子で比較できます。

Integer は Number のサブタイプですが、 はGenericNumber<Integer>のサブタイプではないため、予想される動作では正しくありません。GenericNumber<Number>それを理解するために、あなたのケースで のインスタンスで set メソッドを呼び出したいとしますGenericNumber<Number>:

GenericNumber<Integer> i = new GenericNumber<Integer>();
Integer ii = 3;
i.setNumber(ii);
GenericNumber<Number> n = i;//suppose it will be consumed by compiler
//in this case it will be tempting to forget about i and use n instead, like in the following lines
Folat f = 2.5f;
n.setNumber(f);
//would be valid because method signature will be 
//public void Number setNumber(Number number)
//but what actually happens is that you will try to call method of class
//GenericNumber<Integer> with signature public void Integer setNumber(Integer number)

ご覧のとおり、最後の行でエラーが発生するため、ジェネリックは注意して使用する必要があります。

ところで、当時は Sun、現在は Oracle のサイトのジェネリックに関するチュートリアル セクション、つまり http://docs.oracle.com/javase/tutorial/java/generics/index.htmlおよび/または http:/ /docs.oracle.com/javase/tutorial/extra/generics/index.html .

于 2012-11-14T07:28:04.117 に答える
0

GenericTest1<Integer>互換性GenericTest1<Number>がなく、それらの間でキャストすることはできません! しかし、整数を公開したくない場合は、境界を使用できます。

GenericTest1<? extends Number> r = g;

rGenericTest1<Integer>実数ですが、宣言では Number へのアクセスのみが許可されます。T は特定されていないため、呼び出すことはできませんset()(OK、null で動作します) が、次のように使用できますget()

g.set(Integer.valueOf(1)); // OK
r.set(Integer.valueOf(1)); // compile ERROR
if (r.get().intValue() == 1) { //OK
    ...  
}
于 2012-11-14T07:02:51.443 に答える