4

私は、すべてのジェネリック型変数が、メソッド「型パラメーター セクション」の先頭にあるジェネリック定義から決定された上限に置き換えられていることを知っています。

これはダイテルの本から

実際には、すべての型パラメーターは、型パラメーター セクションで指定されている型パラメーターのいわゆる上限に置き換えられます。

それによると、このサブコードは真でなければなりません

public  static <E extends Number> void A(  )
 {

E x=  new Double(2.2);

 }

しかし、コンパイラはE x= new Double(2.2);でコンパイル エラーだと教えてくれます 。double は numberであるため、これは true でなければなりません。

キャストによって一般的に問題を処理および解決する方法を知っていますが、なぜこれが発生するのですか?

4

4 に答える 4

6

数字だからといってE、それが であるとは限りませんDouble

E が Integer だったらどうなるでしょうか。E は依然として Number ですが、Double を Integer に代入しています。そのため、キャスト動作は一貫しており、Numberはあらゆる種類の異なる型にすることができ、E も同様です。

Op の編集: Deitel ステートメントは依然として正しいです。Double を Number または Object に割り当てる場合、キャストは必要ありません。ただし、この場合、E は「上向き」に割り当てているのではなく、2 つの異なる Number 型の間で「横方向」に割り当てています。E が Short または Integer の場合、キャストせずに Double を割り当てることは期待できません。

于 2013-05-29T21:43:37.253 に答える
3

を指定した場合E extends Number、これEは の任意のサブタイプNumber、またはNumberそれ自体であることを意味します。たとえば、、 、 などになるE可能性があります。これが、コードがコンパイルされない理由です。IntegerLongDoubleEIntegerDoubleInteger

于 2013-05-29T21:44:46.633 に答える
2

それでも、これは完全に機能します!

public static <E extends Number> void A() {
  E x = (E)new Double(2.2);
}

コンパイラに優しくしてください。あなたがする必要があるのは、あなたが何を意味するかを伝えることだけです。

そして - もちろん - 私たちは実際にコンパイラに嘘をついているので、次のような恐ろしいことをすることができます:

public class Test {
  public static <E extends Number> E makeOne() {
    E x = (E) new Double(2.2);
    return x;
  }

  // Some real compiler abuse.
  public void test() {
    Integer one = Test.<Integer>makeOne();
    Double two = Test.<Double>makeOne();
    Number three = Test.<Double>makeOne();
  }

}

自宅の読者へ...これはジェネリックの使用方法ではありません。

ああ、ちなみに、問題が発生している理由は、キャストせずに型が一致していないためです。

あなたの問題は概念的なものです。Generic 句で渡される型は、最終的に使用することを決定した型のプレースホルダーで<E extends Number>はありません。どのタイプを使用するかについての決定を遅らせているだけではありません。句に一致する型のみを使用することを約束しています。その約束を破った場合、コンパイラは警告する必要があります。

あなたのコードが受け入れられない理由は、あなたがまさにそれを行っているからです。あなたはその約束を破っています。呼び出し元は任意のものを使用でき Numberますが、特定のNumber( Double) を使用するため、自分で定めた規則を破っていて、コンパイラがあなたに告げていると言っています。

于 2013-05-29T21:50:55.063 に答える
0

あなたが知っているのは、E拡張することだけですNumber。タイプは であるE可能性がありInteger、これは のサブクラスでもありNumberます。

assignを typenew Double(2.2)という名前の変数に割り当てるのはあまり意味がありません。xInteger

于 2013-05-29T21:46:34.870 に答える