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

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

多種類型的Java列表是否可能

多種類型的Java列表是否可能

30秒到達戰場 2021-11-11 15:57:04
昨天我偶然發現了一些我無法解釋的奇怪的 Java/Spring/IntelliJ 行為。這是一個使用 jdk1.8.0_152 制作的 Spring Boot 應用程序。我運行了這個簡單的 SQL 來填充我的數據庫:CREATE TABLE TEST_ORGANIZATION(    ID NUMBER(19) NOT NULL,    NAME VARCHAR(255) NOT NULL);INSERT INTO TEST_ORGANIZATION (ID, NAME) VALUES ('1', 'test1');INSERT INTO TEST_ORGANIZATION (ID, NAME) VALUES ('2', 'test2');這是我的實體類:@Data@NoArgsConstructor@Entitypublic class TestOrganization {    @Id    private Long id;    @NotNull    private String name;}還有我的 JPA 存儲庫:public interface TestOrganizationRepository extends JpaRepository<TestOrganization, Long> {    @Query("SELECT new map(id as key, name as value) FROM TestOrganization")    List<Map<String, String>> findAllAndMapById();}這就是事情變得混亂的地方。我編寫了一個簡單的單元測試來檢查值,但結果在第二次斷言時失?。篅Testpublic void shouldGetDocumentByName() {    List<String> values = testOrganizationRepository.findAllAndMapById()            .stream()            .flatMap( m -> m.values().stream() )            .collect( Collectors.toList() );    assertThat( values ).isNotEmpty();    assertThat( values ).allMatch( n -> n instanceof String );}使用 IntelliJ 進行調試時,它顯示如下值:這怎么可能?為什么我可以在字符串列表中擁有 Long 值?還: values.add(1L) // fails to compile values.get(0).getClass().name // returns java.lang.String values.get(1).getClass().name // returns java.lang.Long
查看完整描述

3 回答

?
繁星點點滴滴

TA貢獻1803條經驗 獲得超3個贊

這是可能的,因為 Java 中的類型擦除。簡而言之,這意味著在運行時 Java 不知道您的泛型類型,因此任何List對象都使用Object類型進行操作。泛型具有編譯類型安全性。但是您可以更詳細地了解類型擦除,例如這里。


您可以自己模仿的相同行為:


public static void main(String[] args) {

    List<String> list = new ArrayList<>();

    addToList(list);

    System.out.println(list);

}


private static void addToList(List list) {

    list.add(1L);

    list.add(42);

    list.add("String");

    list.add(new Runnable() {

        @Override

        public void run() {}

    });

}

只要您不嘗試將列表條目作為字符串進行操作,此代碼就可以正常工作。但是當你添加如下內容時:


for (String s : list) {

    System.out.println(s);

}

你會得到java.lang.ClassCastException。


因此,在編譯時,您可以使用List<String>,但在運行時,Java 只知道List.


查看完整回答
反對 回復 2021-11-11
?
幕布斯7119047

TA貢獻1794條經驗 獲得超8個贊

是的,你可以,這是一個小例子


public static void main(String args) {

        List objects = new ArrayList();

        objects.add("string");

        objects.add(1L);


        List<String> onlyStrings = objects;


    }

如果您愿意,您可以將非通用列表轉換為 List(您會收到一堆編譯器警告)。


查看完整回答
反對 回復 2021-11-11
?
鴻蒙傳說

TA貢獻1865條經驗 獲得超7個贊

考慮以下示例:


public static void main(String[] args) {

    List a = new ArrayList();

    a.add("a");

    a.add(1L);


    List<String> b = new ArrayList(a);


    System.out.println(b);

}

這輸出


[a, 1]

以上是合法的,因為java執行類型擦除,從而在運行時丟棄元素類型信息。這意味著每個 List 本質上都是一個 List 并且可以包含多個類實例。


public interface List<E> extends Collection<E>

轉換為


public interface List extends Collection

在編譯時。


如果 E 被綁定,即 E 擴展了 MyClass,它將被轉換為 MyClass。


在您的情況下,您正在為每一行實例化一個地圖,沒有類型界限,您正在對其進行平面映射,然后將其收集到一個列表中,這實際上與我的示例相同,因此是合法的。


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

添加回答

舉報

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號

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