title: Java collection, generics and abstract class: concrete class information lost
body: <p>I have class <code>Bar</code> (and potentially a number of other classes) which extends abstract class <code>AbstractFoo</code>. When converting an instance of <code>Bar</code> to <code>FooDTO</code>, the concrete class is detected.</p>
  
  <p>However, when converting a collection of <code>Bar</code> instances to a list of <code>FooDTO</code>, the concrete class information is lost, and conversion is performed on the basis of <code>AbstractFoo</code>.</p>
  
  <p>What's going wrong here?</p>
  
  <pre><code>public class CollectionGenericsNGTest {
  
  
      public static abstract class AbstractFoo { }
  
      public static class Bar extends AbstractFoo { }
  
      public static class FooDTO {
          final boolean isBar;
  
          public FooDTO(AbstractFoo f) {
              this.isBar = false;
          }
  
          public FooDTO(Bar b) {
              this.isBar = true;
          }
      }
  
      public static class FooDTOList {
          List&lt;FooDTO&gt; list;
  
          public FooDTOList(Collection&lt;? extends AbstractFoo&gt; source) {
              list = source.stream()
                      .map(entry -&gt; new FooDTO(entry))
                      .collect(Collectors.toList());
          }
  
          public List&lt;FooDTO&gt; getList() {
              return list;
          }
      }
  
      @Test
      public void testDTO() {
          Bar b = new Bar();
          FooDTO f = new FooDTO(b);
  
          assertTrue(f.isBar);
      }
  
      @Test
      public void testDTO_abstract() {
          AbstractFoo b = new Bar();
          FooDTO f = new FooDTO(b);
  
          assertTrue(f.isBar); // &lt;-- fails, too
      }
  
      @Test
      public void testDTOList() {
          Bar b = new Bar();
          List&lt;Bar&gt; collection = Arrays.asList(b);
          FooDTOList list = new FooDTOList(collection);
  
          FooDTO f = list.getList().get(0);
          assertTrue(f.isBar); // &lt;--- this fails!
      }
  
  }
  </code></pre>