0

次のコードを検討してください

class SomeClass {
}

class GenericsExample<E extends SomeClass> {

    public void createError() {
        process(new SomeClass()); //Compiler error!
    }

    public void createWorking() {
        E some = new SomeClass(); //Compiler error!
        process(some);
    }

    public void process(E object) {
    }
}

public class Sandbox {
    public void run() {
        new GenericsExample<SomeClass>().process(new SomeClass()); //Not a compiler error?!
        new GenericsExample().process(new SomeClass()); //Still not a compiler error?!
    }
}

最初のエラーのメッセージ (2 番目のエラーは本質的に同じものです)

required: E
found: SomeClass
reason: actual argument SomeClass cannot be converted to E by method invocation conversion
where E is a type-variable:
  E extends SomeClass declared in class GenericsExample

これは SomeClass を E にキャストすることで修正できますが、なぜそうしなければならないのでしょうか? メソッドが引数として E を取り、E が SomeClass を拡張する場合、引数として SomeClass を受け入れるべきではありませんか? これが警告ではなくコンパイラ エラーなのはなぜですか?

また、ジェネリック型を宣言していない場合でも、これが外部クラスに適用されないのはなぜですか? GenericsExample と Sandbox でルールが大きく異なるのはなぜですか?

4

3 に答える 3

2
E extends SomeClass

あなたが書いたように、Eは と同じではありませんSomeClass

書くことができないのと同じように、基本型のインスタンスをより派生した型の変数に割り当てることはできません

Button myButton = new Control();  // Not actually a button!

type の変数に割り当てることができるのEは、 type のインスタンスだけですE

クラスの外では、 . を使用しているためにのみ機能しますGenericClass<SomeClass>。ありE ます SomeClass

于 2013-06-12T18:34:45.803 に答える
1

より具体的な例に置き換えるだけで明確になると思います。

EandSomeClassをgetに交換したと仮定しますInteger(Number実装ではなく拡張を許してください) Integer extends Number。この場合、次のことができないことは明らかです

Integer i = new Number();

Integer は Number よりも具体的であるためです。

于 2013-06-12T18:36:01.513 に答える
0

また、ジェネリック型を宣言していない場合でも、これが外部クラスに適用されないのはなぜですか?

それらは異なるケースであるため:

new GenericsExample<SomeClass>().process(new SomeClass()); 

これはコンパイラ エラーではありませんSomeClass。ここでは、. E extends SomeClass

new GenericsExample().process(new SomeClass()); 

そして、それはジェネリックを使用していないため、ジェネリック型の安全性をオプトアウトしています (そして、それに関するコンパイラの警告が表示されます)。

于 2013-06-12T18:39:38.833 に答える