How do you cast a List of supertypes to a List of subtypes?

前端 未结 17 1290
面向向阳花
面向向阳花 2020-11-22 08:43

For example, lets say you have two classes:

public class TestA {}
public class TestB extends TestA{}

I have a method that returns a L

相关标签:
17条回答
  • 2020-11-22 08:50

    With Java 8, you actually can

    List<TestB> variable = collectionOfListA
        .stream()
        .map(e -> (TestB) e)
        .collect(Collectors.toList());
    
    0 讨论(0)
  • 2020-11-22 08:53

    Simply casting to List<TestB> almost works; but it doesn't work because you can't cast a generic type of one parameter to another. However, you can cast through an intermediate wildcard type and it will be allowed (since you can cast to and from wildcard types, just with an unchecked warning):

    List<TestB> variable = (List<TestB>)(List<?>) collectionOfListA;
    
    0 讨论(0)
  • 2020-11-22 08:54

    This should would work

    List<TestA> testAList = new ArrayList<>();
    List<TestB> testBList = new ArrayList<>()
    testAList.addAll(new ArrayList<>(testBList));
    
    0 讨论(0)
  • 2020-11-22 08:55

    You really can't*:

    Example is taken from this Java tutorial

    Assume there are two types A and B such that B extends A. Then the following code is correct:

        B b = new B();
        A a = b;
    

    The previous code is valid because B is a subclass of A. Now, what happens with List<A> and List<B>?

    It turns out that List<B> is not a subclass of List<A> therefore we cannot write

        List<B> b = new ArrayList<>();
        List<A> a = b; // error, List<B> is not of type List<A>
    

    Furthermore, we can't even write

        List<B> b = new ArrayList<>();
        List<A> a = (List<A>)b; // error, List<B> is not of type List<A>
    

    *: To make the casting possible we need a common parent for both List<A> and List<B>: List<?> for example. The following is valid:

        List<B> b = new ArrayList<>();
        List<?> t = (List<B>)b;
        List<A> a = (List<A>)t;
    

    You will, however, get a warning. You can suppress it by adding @SuppressWarnings("unchecked") to your method.

    0 讨论(0)
  • 2020-11-22 08:58

    if you have an object of the class TestA, you can't cast it to TestB. every TestB is a TestA, but not the other way.

    in the following code:

    TestA a = new TestA();
    TestB b = (TestB) a;
    

    the second line would throw a ClassCastException.

    you can only cast a TestA reference if the object itself is TestB. for example:

    TestA a = new TestB();
    TestB b = (TestB) a;
    

    so, you may not always cast a list of TestA to a list of TestB.

    0 讨论(0)
  • 2020-11-22 09:01
    class MyClass {
      String field;
    
      MyClass(String field) {
        this.field = field;
      }
    }
    
    @Test
    public void testTypeCast() {
      List<Object> objectList = Arrays.asList(new MyClass("1"), new MyClass("2"));
    
      Class<MyClass> clazz = MyClass.class;
      List<MyClass> myClassList = objectList.stream()
          .map(clazz::cast)
          .collect(Collectors.toList());
    
      assertEquals(objectList.size(), myClassList.size());
      assertEquals(objectList, myClassList);
    }
    

    This test shows how to cast List<Object> to List<MyClass>. But you need to take an attention to that objectList must contain instances of the same type as MyClass. And this example can be considered when List<T> is used. For this purpose get field Class<T> clazz in constructor and use it instead of MyClass.class.

    0 讨论(0)
提交回复
热议问题