Java使用带有列表和接口的泛型
好的,我的问题是:Java使用带有列表和接口的泛型,java,generics,parameters,Java,Generics,Parameters,好的,我的问题是: 我有一个包含接口的列表-列表a,还有一个扩展该接口的接口列表:列表b。我想设置a=b。我不希望使用addAll()或任何会消耗更多内存的东西,因为我正在做的事情已经非常耗资。我确实需要能够说a=b。我已经试过了List,没有办法做到类型安全 列表不能添加任意的接口s。它毕竟是一个子接口的列表 如果您确信这样做是安全的,即使它不是类型安全的,您也可以这样做 @SuppressWarnings("unchecked") void yourMethodName() { ...
我有一个包含接口的列表-
列表a
,还有一个扩展该接口的接口列表:列表b
。我想设置a=b
。我不希望使用addAll()
或任何会消耗更多内存的东西,因为我正在做的事情已经非常耗资。我确实需要能够说a=b
。我已经试过了List,没有办法做到类型安全
列表
不能添加任意的接口
s。它毕竟是一个子接口的列表
如果您确信这样做是安全的,即使它不是类型安全的,您也可以这样做
@SuppressWarnings("unchecked")
void yourMethodName() {
...
List<Interface> a = (List<Interface>) b;
...
}
@SuppressWarnings(“未选中”)
void yourMethodName(){
...
列表a=(列表)b;
...
}
这项工作:
public class TestList {
interface Record {}
interface SubRecord extends Record {}
public static void main(String[] args) {
List<? extends Record> l = new ArrayList<Record>();
List<SubRecord> l2 = new ArrayList<SubRecord>();
Record i = new Record(){};
SubRecord j = new SubRecord(){};
l = l2;
Record a = l.get( 0 );
((List<Record>)l).add( i ); //<--will fail at run time,see below
((List<SubRecord>)l).add( j ); //<--will be ok at run time
}
}
正如我们刚才所看到的,这仅适用于List
而不适用于任何List
,例如List
问候,,
Stéphane您不能这样做,也不能保证安全,因为List
和List
在Java中是不同的类型。即使可以将子接口类型添加到接口列表中,也不能将两个列表等同于不同的接口,即使它们是彼此的子/超级接口
为什么你这么想做b=a?是否只存储对子接口列表的引用
另外,我建议您在oracle网站上阅读以下文档:
它很好地解释并深入到泛型中。只是为了解释为什么Java不允许这样做:
列表
是一个列表,您可以在其中放置任何实现记录
的对象,您取出的每个对象都将实现记录
列表
是一个列表,您可以在其中放置任何实现子记录的对象
,并且您取出的每个对象都将实现子记录
如果只允许将列表
用作列表
,则允许:
List<SubRecord> subrecords = new ArrayList<SubRecord>();
List<Record> records = subrecords;
records.add(new Record()); // no problem here
SubRecord sr = subrecords.get(0); // bang!
要查看和了解该变化,请执行以下操作:
void addSubrecords(List<? super Subrecord> subrecords) {
...
}
List<Record> records = new ArrayList<Record>();
addSubrecords(records);
recordkeeper.records = records;
void addSubrecords(List因此,我的一位朋友找到了一个相当简单的解决方案:
recordKeeper.myList = (List<Record>)(List<? extends Record>)records;
recordKeeper.myList=(List)(List这项工作,但你应该得到警告
@Override
// Patient is Interface
public List<Patient> getAllPatients() {
// patientService.loadPatients() returns a list of subclasess of Interface Patient
return (List<Patient>)(List<? extends Patient>)patientService.loadPatients();
}
@覆盖
//病人是界面
公共列表getAllPatients(){
//loadPatients()返回接口Patient的子类列表
return(List)(List)如果你不想添加,为什么要在你的问题中写:“但是我不能在列表中添加接口,只有子接口?”@MirroredFate,我错了。我不明白。这里只有一个列表--new ArrayList()
。您希望有两个变量引用此列表,myList
和records
,对吗?@Snicolas如果我将泛型添加到列表中,使其成为List@MirroredFate,并且您希望能够执行myRecordKeeper.myList.add(anyRecord)
?@MirroredFate,您必须给出代码来解释如何使用泛型列表(超级类型)。如果不修改列表的定义,就没有干净的方法可以做到这一点。假设您这样做了,那么这将是正确的,而事实并非如此:类Record2扩展了记录{…};recordKeeper.myList=records;recordKeeper.myList.add(new Record2())
你能理解为什么它是错的吗?如果你使用了“?扩展记录”,那么你的意思是你不知道列表的确切类型,所以你必须使用typecast(在列表上)为了添加元素。Java会知道列表上的每个元素都扩展了记录,因此您可以从中获取记录对象,但您不能插入任何记录,因为列表是用Java不知道的类型键入的。您想参加聚会,但看门人丢失了来宾列表。因此,八年后,我用rea回顾了这个问题我认为Java编译器(以前?有一段时间没有使用Java)只是个哑巴,在LSP方面不好。因此,实际上有一种巧妙的方法可以解决这个问题。List a=(List)(List)(我怀疑您是否可以使用此方法在运行时添加记录。此外,第二个强制转换(最右边的一个)似乎不需要。不,在你的解释中,说ListIt在运行时确实有效是错误的。你把它倒过来了。ListOk。继承是一种特殊化。对吗?所以,当你说“扩展记录的所有东西都是记录”时,这是正确的。但是,如果您对容器所说的是正确的:因为列表可以保存记录(以下语句在java中有效:List.add(new Record());),所以对于扩展它的类来说应该是正确的。而且youc不能向列表中添加记录。我要试试你的列表啊,遗憾的是,我仍然找不到方法来使用它,这样它就可以完成与我的答案相同的事情。我有很高的希望。:(没有方法以类型安全的方式来做。你可以欺骗编译器(由于VM不知道类型,如果您不使用special,它将在运行时工作),但它不是类型安全的。不,List如果您高兴,好吧。只要确保当您在其他地方更改程序时,如果它在另一个点由于这种非类型安全转换而开始中断,您不会感到惊讶。
List<Record> records = new ArrayList<Record>(subrecords);
void addSubrecords(List<? super Subrecord> subrecords) {
...
}
List<Record> records = new ArrayList<Record>();
addSubrecords(records);
recordkeeper.records = records;
recordKeeper.myList = (List<Record>)(List<? extends Record>)records;
@Override
// Patient is Interface
public List<Patient> getAllPatients() {
// patientService.loadPatients() returns a list of subclasess of Interface Patient
return (List<Patient>)(List<? extends Patient>)patientService.loadPatients();
}