假设您有一些类型为T
的课程:
class MyClass<T extends SomeOtherClass> {
....
}
现在,您希望将此类的实例存储到集合中,但您并不真正关心该类型。我想表达如下:
private final List<MyClass> entries = new ArrayList<>();
有没有什么好的理由/优势来编写以下内容?
private final List<MyClass<?>> entries = new ArrayList<>();
甚至:
private final List<MyClass<? extends SomeOtherClass> entries = new ArrayList<>();
我自己只能找到一个不好的理由:只要MyClass
的类型定义发生变化(例如添加其他类型),就必须改变List<MyClass<?>>
或{{1}你的代码中也有定义。
更新
更新我的问题:
为什么编译器在写List<MyClass<? extends SomeOtherClass>>
(甚至MyClass
)时无法跟踪List<MyClass>
的类型?他知道List<MyClass<? extends SomeOtherClass>>
被定义为MyClass
,所以当你写MyClass<T extends SomeOtherClass>
时,他为什么不能/允许这样做?
换句话说,为什么List<MyClass>
不等于List<MyClass>
(甚至List<MyClass<?>>
)?编译器有自己的所有信息,afaik。
答案 0 :(得分:1)
当您不需要再次引用该类型时,class MyClass<T extends SomeOtherClass>
通配符非常有用,因此您无需创建特定的标识符。
您的第一个代码段以T
开头。当class MyClass<T extends SomeOtherClass> {
private final List<T> aListOfT;
public T getSomething() {
return this.aListOfT.get(0);
}
稍后重要时,这可能是必要的,可能是声明字段参数或返回类型。例如:
MyClass
由于List<MyClass>
是泛型类型,因此应对所有对它的引用进行限定,以避免可避免的运行时错误。因此,当您声明MyClass
时,您会收到编译器警告您使用原始类型MyClass
。如果您不关心代码中的那个位置?
符合哪种类型,那么您使用val1 = df1['val1']
val2 = df1['val2']
val11 = df2['val11']
val22 = df2['val22']
SameOrNot = None
if val1 == val11 and val2 == val22:
SameOrNot = True
else:
SameOrNot = False
pd.to_csv('output.csv', header = [val1, val2, val11, val22, SameOrNot])
告诉编译器您不关心并让它跟踪类型并检查所有操作的有效性。
答案 1 :(得分:0)
您的第一个声明意味着,您未提供有关未来反射系统的通用数据的任何信息,可以由为主程序编写的插件使用。
第二个声明告诉他们,该字段包含一个Object泛型。
第三个是更具体的,它意味着,反射系统知道,这个领域的细节是什么。
答案 2 :(得分:0)
使用第一种类型,java将假定泛型类型是Object。原因是,1.5版引入了泛型。在此之前,集合类将所有内容存储为对象。出于兼容性原因,不提供通用参数意味着您正在使用对象。
第二种类型只是说你不知道或不关心它是什么类型。编译代码时会保留此信息。所以可能使用你的代码的其他程序员会知道你不在乎。
由于java的类型擦除,这两者在运行时没有区别。
用最后一个表格你说: 我不在乎它是什么,但它必须是SomeOtherClass或派生类型。这与:
相同List<MyClass<SomeOtherClass>>
您也可以反过来这样做:
List<MyClass<? super SomeOtherClass>>
说你不关心它是什么类型,除非它是SomeOtherClass的超类型。