2

I have a class with the following definition:

public abstract class A<T> implements Iterator<B> {}

The following call to next() will return an Object rather than a B:

A a = new SomethingThatExtendsA();
B b = a.next();

I've searched for quite awhile and haven't been able to figure out why this next() call fails to compile. Is anyone able to describe this behavior for me?

Edited original to be templated, as this seems to matter.

Edit for additional clarification: This is a compile-time issue, not a runtime issue. The implementation of SomethingThatExtendsA(); should be irrelevant in this case at compile-time.

4

3 に答える 3

5

したがって、次のコードがあります。

public abstract class A<T> implements Iterator<B> {}
[...]
A a = new SomethingThatExtendsA();
a.next();

Aはジェネリック型ですがa、生の型で定義しています。の右側は無視して=、静的型のみに関心があります。

A/*<Something>*/ a = ...;

コンパイラはここで警告を出します。(少なくとも比較的最近のバージョンの javac で十分rawtypesです。Oracle javac での警告です。) コンパイラの警告に注意してください。(javacが警告を出さなくてよかった?)

だから今、私たちはaraw であり、 である型を持つ状況にありIterator<B>ます。これは、驚くほど難しい意味を持つ、本当に混乱する状況です。これを行うべきではありません-ジェネリック型と生の型を混在させることは避けるべきです。したがって、Java 言語仕様は単純な方法を取り、部分的なジェネリック型情報を破棄します。

したがって、raw 型とジェネリック型を混在させないでください。すべてのジェネリックを使用するだけで問題ありません。

于 2012-07-11T23:33:38.690 に答える
0
public abstract class A implements Iterator<B> {}
class B {}
class SomethingThatExtendsA extends A {
// implement A methods
}
A a = new SomethingThatExtendsA();
a.next();

This code is pretty correct and returns B object. Probably you missed something in SomethingThatExtendsA class.

Test it by calling:

B b1 = new Object();  // compilation error
B b2 = a.next(); // all is OK

UPDATE: Change signature in SomethingThatExtendsA from public Object next() { } to public B next() {}

于 2012-07-11T23:12:33.560 に答える
0

ここSomethingThatExtendsAでは、クラスはニシンです。同じ問題が発生します

List<String> list = new ArrayList<String>();
list.add("foo");
Iterator iterator = list.iterator(); // you should get a warning on this line...
String foo = iterator.next(); // ... and a compile error on this line

問題は、生の型が下位互換性のためだけの恐ろしい醜いハックであり、それらの周りのすべてのジェネリックが機能しなくなることです。具体的には、、 、さらには と同じ型Iteratorはありません。代わりに、 「ジェネリック以前のバージョンの Java でコンパイルした場合に得られたであろうクラス」を意味します。のジェネリック以前のバージョンは常に返されたため、それが得られます。また、キャストなしで type の値をより具体的なタイプ ( 、または typeなど)に割り当てることはできません。Iterator<String>Iterator<Object>Iterator<?>IteratorIteratorIteratorObjectObjectStringB

Java 言語仕様には、次のように書かれています。

生の型の使用は、レガシー コードの互換性への譲歩としてのみ許可されています。Java プログラミング言語に汎用性が導入された後に記述されたコードで生の型を使用することは、強くお勧めできませんJava プログラミング言語の将来のバージョンでは、生の型の使用が禁止される可能性があります。

于 2012-07-12T00:31:42.077 に答える