1

私は次のコードを持っています:

public class Foo {

    interface Coo<T> {
        public T cool();
    }

    abstract class Bar<T extends Bar<T>> implements Coo<T>  {

        @SuppressWarnings("unchecked")
        T doSomething() {
            return (T) this;
        }

        @SuppressWarnings("unchecked")
        @Override
        public T cool() {
            return (T) this;
        }

    }

    class FooBar extends Bar<FooBar> {
        @Override
        public FooBar cool() {
            return super.cool();
        }

    }
}

(この)オブジェクトタイプへのキャストが安全でないのはなぜですか?BarがCooを実装する場合、返されるクールは、Barまたはそのサブクラスを拡張するタイプTでなければならないという一般的な言い回しではありませんか?

4

2 に答える 2

3

thisinにBarは型Bar<T extends Bar<T>>がありますが、はないためT、コンパイラは。の警告を生成しますBar#doSomething。以下は警告を生成しません。

abstract class Bar<T extends Bar<T>> {

    Bar<T> doSomething() {
        return this;
    }

}

の本体は、そうではないサブタイプであるとBar#cool期待しています。で、タイプがあり、のサブタイプですが、ではありません。thisTBar#coolthisBar<T extends Bar<T>>Coo<T>T

于 2012-12-11T01:02:42.717 に答える
1

Tを拡張Bar<T>しますが、Bar<T>(のタイプthis)は拡張しませんT

想像

class A extends Bar<A> { ... }
class B extends Bar<A> { ... }

次に、メソッドは次のように継承されます。

class B {
    A doSomething() {
        return (A) this;
    }
}

これは明らかに正しくありません。

ジェネリックでやりたいことをすることはできません。それは人々の間の大きな誤解です。彼らは、再帰的な境界によってセルフタイプが可能になると考えています。しかし、再帰的な境界は、Javaではほとんど役に立ちません。あなたが人々が書くのを見る場所の99%はinterface Bar<T extends Bar<T>>、それを書くのと同じくらい良いでしょうinterface Bar<T>

于 2012-12-11T03:52:40.427 に答える