具有返回列表的方法的通用接口

时间:2016-08-04 14:20:34

标签: java generics javac

我有一个通用接口(Pack<A extends PackAnimal>),其中一个方法返回List<A>。今天我发现,如果在实现接口的类中我忘记了类(class XXX implements PackAnimal),则不会在编译时检查返回类型并在执行期间失败

interface PackAnimal {
}
class Buffalo implements PackAnimal {
}

interface LonelyAnimal {
}
class Puma implements LonelyAnimal {
}

interface Pack<A extends PackAnimal> {
    List<A> getMembers();
}

class PumaPack implements Pack {

    @Override
    public List<Puma> getMembers() {
        return null;
    }
}

为什么?如果声明中有任何类型的错误,编译将失败,我怎么强制呢?

2 个答案:

答案 0 :(得分:2)

您的列表以未知类型声明。使用班级类型:

interface Pack<A extends PackAnimal> {
    List<A> getMembers();
}

// won't compile because Puma not within bound
class PumaPack implements Pack<Puma> {
    List<Puma> getMembers() {return null;}
}

// compiles OK
class BuffaloPack implements Pack<Buffalo> {
    List<Buffalo> getMembers() {return null;}
}

但你无法阻止某人编写原始(缺失类型)实现,就像你的PumpPack示例一样,但是你会得到一个编译器警告

// compile warning
class PumaPack implements Pack {
    List getMembers() {return null;}
}

如果有警告,则将编译设置为失败:

javac -Werror ...

然后即使对于原始类型,您也将实现目标。

答案 1 :(得分:1)

您遇到使用Raw Types的可怕而奇怪的结果。

基本上,如果你错过了<...>任何地方,那么编译器应该将你的代码视为遗留代码,并且不应该进行大量的正常类型检查。 MOst编译器尽力而为,但在检查过程中留下了一些漏洞。

interface PackAnimal {
}

class Buffalo implements PackAnimal {
}

interface LonelyAnimal {
}

class Puma implements LonelyAnimal {
}

interface Pack<A extends PackAnimal> {
    // Obviously fine.
    List<A> getMembers();
}

// Raw type so no checking.
class PumaPack implements Pack {

    @Override
    public List<Puma> getMembers() {
        // Raw typed class so Puma isn't checked for PackAnimal super.
        return Arrays.asList(new Puma());
    }
}

class Six {

}

// Properly typed so Raw Types not happening.
class SixPack implements Pack<Six> {

    @Override
    // NOT ALLOWED: Attempt to use incompatible return type!!!
    public List<Six> getMembers() {
        return null;
    }
}