Java: casting from list <B> to list <a> when B implements A?

I have the following class and interface:

public interface A { } public class B implements A { } 

I have a List objects B that I need to pass to a List objects A :

 List<B> listB = new List<B>(); listB.add(new B()); // dummy data listB.add(new B()); // dummy data listB.add(new B()); // dummy data List<A> listA = (List<A>) listB; 

The last line above the results in the compilation error "Cannot be selected from list <B> to List <A>". I tried to get around this as follows:

 List<A> listA = Arrays.asList((A[]) listB.toArray()); 

Unfortunately, this raises a ClassCastException . Does anyone know how I can solve this?

+4
source share
5 answers

You can’t throw it like that. Create a new one:

 List<A> listA = new ArrayList<A>(listB); 

The constructor accepts Collection<? extends A> Collection<? extends A> . He will point to the same links anyway.

+13
source

Instead of struggling with a language function, you must learn to use it correctly.

Instead of asking how to use unsafe drops to eliminate the error, it is instructive to first understand why the error occurs; why, what you are asking to do is unsafe (because you can add A to the list using listA and then pull it out of the list as B with listB ).

Then you must explain why you think your use case does not start in an unsafe scenario. Because the answer to this question will give a hint on how to change the code so that it works correctly with generics.

  • If you say this is unsafe because you never add anything using listA , then you should change the type of listA to List<? extends A> List<? extends A> . That way, you can directly assign listB without any casts, and you cannot add anything to it using listA (except null ).
  • If you say this is unsafe because you never get anything using listB , then why not change the type of listB to List<A> in the first place?
+8
source

You can just use type erase if you know the operation is safe. This triggers a warning that you can turn off with @SuppressWarnings

 List<A> listA = (List) listB; 

The reason the compiler is having difficulty with a simple application is that you can now add the C class, which also implements A. Except that your original list has been modified and now contains C, even if you indicated that it should not.

+5
source
 List<A> listA = (List<A>)(List<?>) listB; 

Not recommended.

+2
source

I'm sure you need to make the entire List <A> (weird parsing there) and when adding new B objects they are thrown using (A)

 listA.add( (A) new B()); // dummy data 
+1
source

All Articles