Java Generics:"嵌套"类型参数?

时间:2016-11-02 12:59:00

标签: java generics polymorphism type-parameter

编辑:是的,这可能是重复的。但另一个问题类似于"什么是电锯?如何使用它?"我更喜欢"我正试图在这里用这台机器钻一个洞而且它不起作用 - 它是什么?"。当然答案是"不要使用电锯!"一旦你知道你正在处理电锯,就很容易找到。

但我甚至不知道我的问题与"原始类型与外卡相关"因此没有找到这个问题 - 所以也许这个问题对像我这样的人来说仍然有用。

原始问题我们说我有以下数据结构代表我的用户界面中的项目:

public static abstract class RowItem<T> {

    public final T value;

    public RowItem(T value) {
        this.value = value;
    }
}

现在,我想做以下事情:

public static abstract class EpgRowItem<T> extends RowItem<Pair<String, T>> {

    public EpgRowItem(Pair<String, T> value) {
        super(value);
    }
}

public static final class EpgRowProgramItem extends EpgRowItem<Program> {

    public EpgRowProgramItem(Pair<String, Program> value) {
        super(value);
    }
}

public static final class EpgRowOtherDateItem extends EpgRowItem<LocalDate> {

    public EpgRowOtherDateItem(Pair<String, LocalDate> value) {
        super(value);
    }
}

所以,在单词中:EpgRowItemRowItem,其中包含Pair,其中第一个成员始终是String,第二个成员可以是任何内容。此外,EpgRowProgramItemEpgRowItem,其中该对的第二个成员是Program。同样,EpgRowOtherDateItemEpgRowItem,其中第二个成员是LocalDate

这似乎有效,直到我在我的代码中的其他位置:

List<OverlayPresenter.EpgRowItem> programs = ...;
OverlayPresenter.EpgRowItem epgRowItem = programs.get(0);
String channelId = epgRowItem.value.first; // DOESN'T COMPILE?!

我觉得编译器应该知道epgRowItem.value必须始终是Pair<String, ?>,因此epgRowItem.value.first必须始终是String

实际上,它似乎甚至不知道第一部分,i。即以下不编译:

Pair<String, ?> pair = epgRowItem.value; // epgRowItem.value is an Object?!

我做错了什么?我只是过多地问过Java的泛型?

1 个答案:

答案 0 :(得分:4)

您遇到了麻烦,因为您使用的是原始类型<div class="svg-counter"> <svg class="counter" x="0px" y="0px" viewBox="0 0 776 628"> <path class="track" d="M723 314L543 625.77 183 625.77 3 314 183 2.23 543 2.23 723 314z"></path> <path class="fill" d="M723 314L543 625.77 183 625.77 3 314 183 2.23 543 2.23 723 314z"></path> </svg> </div> (原始类型是一种参数化类型,您没有为其指定类型参数;这些是因为向后兼容Java 1.4及更早版本而存在): / p>

EpgRowItem

请参阅:What is a raw type and why shouldn't we use it?

使用类型参数,或至少使用通配符:

List<OverlayPresenter.EpgRowItem> programs = ...;
OverlayPresenter.EpgRowItem epgRowItem = programs.get(0);