0

假设我有这样的简单课程

public interface Something{
    public void doSomtehing()
}

class A{
    public int getAVal(){
        return 0;
    }
}

class AWithSomething extends A implements Something{
    public void doSomething{
        //in fact do nothing, HAHA
    }
}

abstract class B{
    public abstract <T extends A & Something> T getAWithSomething()
}

class C extends B{

    //allowed??? gives warnig about unchecked conversion
    public A getAWithSomething {
        return new A();
    }
}

class D extends B{

    //same unchecked warning
    public AWithSomething getAWithSomething(){
        return new AWithSomething();
    }
}

C c = new C();
//not implemented but seems valid
c.getAWithSomething().doSomething();

D d = new D();
d.getAWithSomething().doSomething();

所以我的主要问题是:为什么编译器允许类C只返回一个 A 而不检查它是否在编译时实现接口?

编辑(由于 darijan 的评论):嗯,但我不允许这样声明:

class C extends B{

    //not allowed!
    public Something getAWithSomething {
        return new Something(){ 
            doSomething(){}
         };
    }
}
4

1 回答 1

1

JLS 称之为迁移兼容性。应该允许库实现者在B不破坏客户端 ()的情况下生成他们的 API ( C)。实际上,可以用自定义实现替换Bwith ListgetAWithSomething()withget(int)和,例如 apache commons 。CListFixedSizeList

方法签名中的类型变量被擦除为原始类或接口类型。类型变量TinB.getAWithSomething()被擦除到其最左边的 bound A。迁移兼容性基于生成的方法签名A getAWithSomething()。这意味着覆盖的子类getAWithSomething()必须声明其返回类型A或其子类型。

请注意,您会收到一条警告,上面写着“小心,您将 a 传递AA&Something,这可能会出错”。它可以:调用doSomething()返回的A将抛出一个ClassCastException,因为A不能转换为Something

于 2013-06-17T09:24:36.267 回答