Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java using generics with lists and interfaces

Ok, so here is my problem:

I have a list containing interfaces - List<Interface> a - and a list of interfaces that extend that interface: List<SubInterface> b. I want to set a = b. I do not wish to use addAll() or anything that will cost more memory as what I am doing is already very cost-intensive. I literally need to be able to say a = b. I have tried List<? extends Interface> a, but then I cannot add Interfaces to the list a, only the SubInterfaces. Any suggestions?

I want to be able to do something like this:

List<SubRecord> records = new ArrayList<SubRecord>();
//add things to records
recordKeeper.myList = records;

The class RecordKeeper is the one that contains the list of Interfaces (NOT subInterfaces)

public class RecordKeeper{
    public List<Record> myList;
}
like image 211
MirroredFate Avatar asked Jun 24 '11 23:06

MirroredFate


People also ask

Can you have a list of interfaces in Java?

In Java, the List interface is an ordered collection that allows us to store and access elements sequentially. It extends the Collection interface.

CAN interface have generics?

Generic interfaces can inherit from non-generic interfaces if the generic interface is covariant, which means it only uses its type parameter as a return value.


1 Answers

This works :

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

    }

}

I mean it compiles, but you will have to cast your List<? extends Record> before adding anything inside. Java will allow casting if the type you want to cast to is a subclass of Record, but it can't guess which type it will be, you have to specify it.

A List<Record> can only contain Records (including subRecords), A List<SubRecord> can only contain SubRecords.

But A List<SubRecord> is not a List<Record> has it cannot contains Records, and subclasses should always do what super classes can do. This is important as inheritance is specilisation, if List<SubRecords> would be a subclass of List<Record>, it should be able to contain ` but it'S not.

A List<Record> and a List<SubRecord> both are List<? extends Record>. But in a List<? extends Record> you can't add anything as java can't know which exact type the List is a container of. Imagine you could, then you could have the following statements :

List<? extends Record> l = l2;
l.add( new Record() );

As we just saw, this is only possible for List<Record> not for any List<Something that extends Record> such as List<SubRecord>.

Regards, Stéphane

like image 163
Snicolas Avatar answered Oct 01 '22 11:10

Snicolas