我有Bar擴展抽象類的類(可能還有許多其他類)AbstractFoo。將 的實例轉換Bar為 時FooDTO,會檢測到具體類。但是,在將Bar實例集合轉換為 的列表時FooDTO,會丟失具體的類信息,轉換是在 的基礎上進行的AbstractFoo。這里出了什么問題?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<FooDTO> list; public FooDTOList(Collection<? extends AbstractFoo> source) { list = source.stream() .map(entry -> new FooDTO(entry)) .collect(Collectors.toList()); } public List<FooDTO> 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); // <-- fails, too } @Test public void testDTOList() { Bar b = new Bar(); List<Bar> collection = Arrays.asList(b); FooDTOList list = new FooDTOList(collection); FooDTO f = list.getList().get(0); assertTrue(f.isBar); // <--- this fails! }}
1 回答

HUX布斯
TA貢獻1876條經驗 獲得超6個贊
這里
.map(entry -> new FooDTO(entry))
你總是打電話
new FooDTO(AbstractFoo)
設置this.isBar為 false的構造函數。
即使持有的對象entry具有運行時類型Bar,變量entry也具有類型AbstractFoo,因為它是 a 的一部分Collection<? extends AbstractFoo>,所以編譯器知道該對象必須是 an AbstractFoo,但不知道它是 a Bar。重載解析適用于編譯類型時的引用類型,而不是運行時對象的類型。
如果您想檢查 持有的對象的運行時類型entry,而不是變量類型,您可以考慮使用
this.isBar = (f instanceof Bar);
當你分配到你的領域。這將檢查引用的實際對象的運行時類型f。
在你更簡單的情況下
Bar b = new Bar();
FooDTO f = new FooDTO(b);
構造函數調用被解析為,new FooDTO(Bar)因為您傳遞給它一個類型的引用Bar。
如果您改為:
AbstractFoo b = new Bar();
FooDTO f = new FooDTO(b);
那么構造函數調用將解析為new FooDTO(AbstractFoo),因為您將傳遞一個類型的引用AbtractFoo。
添加回答
舉報
0/150
提交
取消