亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

Java集合、泛型和抽象類:具體類信息丟失

Java集合、泛型和抽象類:具體類信息丟失

HUWWW 2021-11-11 16:38:47
我有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。


查看完整回答
反對 回復 2021-11-11
  • 1 回答
  • 0 關注
  • 227 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號