Java 泛型:"Nested" 类型参数?
Java Generics: "Nested" type parameters?
编辑: 是的,这可能是重复的。但是另一个问题类似于 "What is a chainsaw and how do I use it?" 我的更像是 "I am trying to drill a hole with this machine here and it doesn't work - what's up?"。当然,答案是 "Don't use a chainsaw!",一旦您知道自己在处理电锯,就很容易找到。
但我什至不知道我的问题与 "raw types vs. wild cards" 有关,因此没有找到那个问题 - 所以也许这个问题对像我这样的其他人仍然有用。
原始问题:假设我有以下数据结构,代表我的用户界面中的一个项目:
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);
}
}
所以,换句话说:EpgRowItem
是包含 Pair
的 RowItem
,其中第一个成员始终是 String
,第二个成员可以是任何东西。此外,EpgRowProgramItem
是 EpgRowItem
,其中该对的第二个成员是 Program
。同样,EpgRowOtherDateItem
是 EpgRowItem
,其中第二个成员是 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
.
实际上,它似乎连第一部分都不知道,我。 e.以下也不编译:
Pair<String, ?> pair = epgRowItem.value; // epgRowItem.value is an Object?!
我哪里做错了?我是不是对Java的泛型要求太多了?
您遇到麻烦是因为您使用的是原始类型 EpgRowItem
(原始类型是一种参数化类型,您没有为其指定类型参数;这些类型的存在是因为与 Java 向后兼容1.4 及以上):
List<OverlayPresenter.EpgRowItem> programs = ...;
OverlayPresenter.EpgRowItem epgRowItem = programs.get(0);
参见:What is a raw type and why shouldn't we use it?
使用类型参数,或至少使用通配符:
List<OverlayPresenter.EpgRowItem<?>> programs = ...;
OverlayPresenter.EpgRowItem<?> epgRowItem = programs.get(0);
String channelId = epgRowItem.value.first; // OK
编辑: 是的,这可能是重复的。但是另一个问题类似于 "What is a chainsaw and how do I use it?" 我的更像是 "I am trying to drill a hole with this machine here and it doesn't work - what's up?"。当然,答案是 "Don't use a chainsaw!",一旦您知道自己在处理电锯,就很容易找到。
但我什至不知道我的问题与 "raw types vs. wild cards" 有关,因此没有找到那个问题 - 所以也许这个问题对像我这样的其他人仍然有用。
原始问题:假设我有以下数据结构,代表我的用户界面中的一个项目:
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);
}
}
所以,换句话说:EpgRowItem
是包含 Pair
的 RowItem
,其中第一个成员始终是 String
,第二个成员可以是任何东西。此外,EpgRowProgramItem
是 EpgRowItem
,其中该对的第二个成员是 Program
。同样,EpgRowOtherDateItem
是 EpgRowItem
,其中第二个成员是 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
.
实际上,它似乎连第一部分都不知道,我。 e.以下也不编译:
Pair<String, ?> pair = epgRowItem.value; // epgRowItem.value is an Object?!
我哪里做错了?我是不是对Java的泛型要求太多了?
您遇到麻烦是因为您使用的是原始类型 EpgRowItem
(原始类型是一种参数化类型,您没有为其指定类型参数;这些类型的存在是因为与 Java 向后兼容1.4 及以上):
List<OverlayPresenter.EpgRowItem> programs = ...;
OverlayPresenter.EpgRowItem epgRowItem = programs.get(0);
参见:What is a raw type and why shouldn't we use it?
使用类型参数,或至少使用通配符:
List<OverlayPresenter.EpgRowItem<?>> programs = ...;
OverlayPresenter.EpgRowItem<?> epgRowItem = programs.get(0);
String channelId = epgRowItem.value.first; // OK