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(); 
}