关于java:使用泛型键入安全性

Type safety with generics

我有很多简单的界面:

1
2
3
4
5
6
7
8
9
interface County extends Line{}

interface Country<C extends Line> extends LineContainer<C> {}

interface Line {}

interface LineContainer <L extends Line> {
    public List<L> getLines();
}

以及一种服务方法

1
2
public static <L extends Line,C extends LineContainer<L>> C getContainer( Class<C> containerType, Class<L> lineType ){
    ...somthing...

调用服务方法

1
Country<County> c = getContainer( Country.class, County.class );

不会出错,但检查人员说:

Type safety: The expression of type Country needs unchecked conversion to conform to Country

我不明白:通过调用以County为L-Linetype,C为L的容器,C为C-Type的容器,由Country给出C的容器,我期望类型推断可以得出Country对象将被服务的结论。

有人能解释,为什么我是错的,如果我能实现我想实现的目标,我又如何做到?

背景:我的想法是-作为服务的用户-我可以根据需要自由组合容器和行(只要服务提供商可以提供这些服务)


这是因为编译器不确定Country.class是否与签名Country匹配。Country.class被认为是原始类型。

如果你这样写:

1
2
3
public static <L extends Line, C extends LineContainer<L>> C getContainer(C container, Class<L> lineType) {
    return null;
}

还有:

1
2
3
4
5
6
Country<County> c = getContainer(new Country<County>() {
    @Override
    public List<County> getLines() {
        return null;
    }
}, County.class);

显然这是可行的。

现在假设我将相同的代码拆分成另一种方式:

1
2
3
4
5
6
7
    Country foo = new Country<County>() {
        @Override
        public List<County> getLines() {
            return null;
        }
    };
    Country<County> c = getContainer(foo, County.class);

由于原始类型的原因,这将在编译时再次发出警告。


您的代码的问题是,国家可以有一个扩展行的通用类型C,但是使用您的方法。

1
getContainer( Country.class, County.class );

此方法没有告诉您Country.Class具有County的C类型。因此,理论上,你的回报率C是国家。

不幸的是,除了取消警告之外,没有真正的解决方法。或者您不在国家使用参数,而将C固定到县。

1
public interface Country extends LineContainer<County>

您还可以使用实际对象或供应商等。