Java generics list of lists

This thing surpassed me. I have a class as follows:

public class SpecialList implements List<MyType> { // overriden methods } 

Now I have the following contract for using the method in a higher class:

 public class MyClass { private List<SpecialList> bigList = new ArrayList<SpecialList>(); public void doStuff(List<MyType> list) { bigList.add((SpecialList)list); // does not compile - invalid cast } } 

I'm really not sure what I'm doing wrong here. I have a class that implements the List<MyType> interface, but I can not attribute this class to List<MyType> ? That makes no sense to me.

I'm lost. What should I do to make this work? I believe that this is due to the covariance of generics, but now I do not know what is wrong here. Can someone point in the right direction? Thanks.

+6
source share
7 answers

You defined a List<MyList> (i.e. a list of MyList ). This means that you can only add instances of MyList . If you use addAll() , you can add a list of MyList . But you are trying to add a List<MyType> . MyType definitely not a MyList .

And you obviously can't drop List in MyList .

+1
source

not every List<MyType> (Animal) is MyList (Cow)

you add animals to the list of cows

+3
source

I would suggest some options:

 public class MyClass{ private List<List<MyType>> bigList = new ArrayList<List<MyType>>(); public <E extends List<MyType>> void doStuff(E list) { bigList.add(list); } } 

When you retrieve an item from your large list, you cannot specialize the item as it comes from the general list. If you absolutely need to drop it, your cool architecture may be wrong. Or you can abusively do this:

 public class MyClass{ private List<List<MyType>> bigList = new ArrayList<List<MyType>>(); public <E extends List<MyType>> void doStuff(E list) { bigList.add(list); } public <E extends List<MyType>> E getStuff(Class<E> myType,int i) { List<MyType> obj = bigList.get(i); if(myType.isInstance(obj)) return (E) obj; throw new SomeErrorHere("invalid type for index"); } } 
+2
source

From what I remember, the correct way to type list is using generics. Sort of:

 bigList.add((List<MyList>)(List<?>)list); 

However, I am not sure about the theory of this code.

+1
source

Why does this error occur

The code is formally correct. You can apply almost any object to any other object, and the code will be compiled. If the cast is not valid, a ClassCastException runtime will be ClassCastException .

Your IDE may detect insecure snooping and complain about them during compilation. Or as a warning, or as an error. This is a configuration issue. Obviously, the OPs IDE is configured so that such code smells like a compilation error

Why is this cast unsafe

You can answer your question by answering this:

Can you create a List<MyType> that is not a SpecialList ?

You cannot drop List<MyType> to SpecialList , because there may be objects that will be List<MyType> and really not be SpecialList .

Decision

Change application architecture

There are two things you can do: either use the SpecialList class throughout your code, or use the generic List<MyType> .

In other words, either change:

doStuff(List<MyType> list) to doStuff(SpecialList list)

or change

private List<SpecialList> bigList to private List<List<MyType>> bigList

You must decide whether you want a common list of interfaces or your own class to be used everywhere. Remember that you can alaways cast SpecialList to List<MyType> , because all instances of SpecialList are also instances of List<MyType> . This does not work the other way around.

Make sure the cast is always valid.

If you absolutely want this project to work, use instanceof to check if the list is SpecialList . For instance:

 public void doStuff(List<MyType> list) { if (list instanceof SpecialList) { bigList.add((SpecialList)list); } else { SpecialList sl = new SpecialList(list); // I hope you have that constructor bigList.add(sl); } } 
+1
source

This works in my Eclipse, this is the SpecialList class, Hello is the MyType class of the class

 package a; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.ListIterator; public class SpecialList implements List<Hello> { //Overridden methods } 

This is myclass

 package a; import java.util.ArrayList; import java.util.List; public class MyClass { private List<SpecialList> bigList = new ArrayList<SpecialList>(); public void doStuff(List<Hello> list) { bigList.add((SpecialList)list); //compiles good } public static void main(String[] args) { new MyClass().doStuff(null); } } 

Missing compile-time error or runtime exception

0
source
 List <MyList> is not same as List <MyType>. 

Let's make it simple, look at the following few lines:

  *List<MyList> myList = new ArrayList<MyList>(); //1 myList.add(new MyType);//2 ......Compile ERROR* 

If you try to add an instance of MyType to the List<MyList> , it will give an ERROR message.

Why:

  • Generics means a parameterized type.
  • Generic adds TYPE SAFETY.
  • This means that with a common type, everything is automatic and implicit,
    they do not require typing when adding and restoring an object
    from the list explicitly.

Real time scenario:

If the department of vehicles supplies a list of drivers. We believe that a List<Driver> is a List<Person> , assuming Driver is a subtype of Person.

If this is the case, we can add to the list of new people who are NOT drivers.

That all people are NOT drivers.

The solution to the above problem:

You can use Wildcards with Generics. Check out this link from the document http://docs.oracle.com/javase/tutorial/extra/generics/wildcards.html

0
source

Source: https://habr.com/ru/post/945913/


All Articles