4

我有一堆简单的接口:

interface County extends Line{}

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

interface Line {}

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

和一个服务方法

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

调用服务方法

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

没有错误,但检查器说:

类型安全:类型 Country 的表达需要未经检查的转换才能符合 Country

我不明白:通过以 County 作为 L-LineType 调用服务方法,C 是 L 的容器,C 由 Country 作为 C-Type 给出,因此,我预计类型推断会得出结论,即 Country对象将被送达。

谁能解释一下,为什么我错了,我是否以及如何实现我想要的?

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

4

3 回答 3

1

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

如果你这样写:

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

和:

Country<County> c = getContainer(new Country<County>() {
    @Override
    public List<County> getLines() {
        return null;
    }
}, County.class);

显然这行得通。

现在想象我将相同的代码拆分为另一种方式:

    Country foo = new Country<County>() {
        @Override
        public List<County> getLines() {
            return null;
        }
    };
    Country<County> c = getContainer(foo, County.class);

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

于 2018-06-08T09:51:01.440 回答
0

我想我解决了...

我的问题中的主要错误是,我想在容器中定义线条元素。现在我在 Line 中定义它所属的 Header。

interface Line<R> {}

然后,我定义了一个 LineContainer,它为定义的 Type 提供 Lines

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

现在我可以定义一个通用的服务方法(看起来与我上面的方法略有不同):

public static <H,L extends Line<H>,C extends LineContainer<H,L>> C getContainer( Class<C> containerType, Class<L> lineType ){
   // ...something...
}

像这样定义国家和县:

interface County extends Line<Country>{}
interface Country extends LineContainer<Country,County>{};

我现在可以毫无问题地使用:

LineContainer<Country,County> container = getContainer( Country.class, County.class );

LineContainer 和 Line 的另一个例子:

interface Note extends Line<Gamut>{}
interface Gamut extends LineContainer<Gamut,Note>{};
LineContainer<Gamut,Note> container = getContainer( Gamut.class, Note.class );

服务方法必须检查是否可以提供所需的类型,但服务的用户不能组合不兼容的类型:

不允许

LineContainer<Gamut,County> container = getContainer( Gamut.class, County.class );

因为县不是色域的“线”...

于 2019-06-03T14:40:53.093 回答
0

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

getContainer( Country.class, County.class );

此方法不会告诉您此 Country.class 具有 County 的 C 类型。因此理论上您的返回 C 将是 Country。

不幸的是,除了抑制警告之外,没有真正的解决方法。或者您不在 Country 中使用参数并将 C 固定为 County。

public interface Country extends LineContainer<County>

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

于 2018-06-08T09:52:14.653 回答