關(guān)于Object[] 強(qiáng)制類型轉(zhuǎn)換的思考

前言

今天群里有位同學(xué)提了一個(gè)關(guān)于Object[]數(shù)組向下強(qiáng)制類型轉(zhuǎn)換的問題,個(gè)人覺得這個(gè)問題還是有必要思考總結(jié)一下,因?yàn)楹芏嗳说谝谎鄱紩?huì)覺得:奇怪,這里怎么會(huì)拋出ClassCastException呢?

正文

首先我們敲一遍這位同學(xué)提的問題

1. 編碼

Coffee.java

模擬數(shù)據(jù)庫查詢實(shí)體咖啡類

public class Coffee {

    private String name;

    private Double price;

    public Coffee() {
    }

    public Coffee(String name, Double price) {
        this.name = name;
        this.price = price;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }
}

模擬業(yè)務(wù)代碼

TestCoffee.java

public class TestCoffee {
    private static List<Coffee> queryFromDatabase() {
        List<Coffee> result = new ArrayList<>();
        Coffee latte = new Coffee("latte", 38.0);
        Coffee latte2 = new Coffee("latte", 28.0);
        Coffee mocha = new Coffee("mocha", 58.0);

        result.add(latte);
        result.add(latte2);
        result.add(mocha);
        return result;
    }

    public static void main(String[] args) {

        // 1. 模擬從數(shù)據(jù)庫查詢出所有咖啡
        List<Coffee> coffees = queryFromDatabase();

        // 2. 取出所有l(wèi)atte拿鐵類咖啡并放入一個(gè)Coffee[]數(shù)組中
        Coffee[] lattes = (Coffee[]) coffees.stream()
                .filter(coffee -> coffee.getName().equals("latte"))
                .toArray();

        // 3. 這里只是測試打印,實(shí)際業(yè)務(wù)代碼可能需要用Coffee[]類型的參數(shù)再去做其他業(yè)務(wù)處理...
        System.out.println("latte coffee number is: " + lattes.length);
    }
}

測試代碼邏輯:
我們首先模擬從數(shù)據(jù)庫中查詢出所有咖啡數(shù)據(jù),利用Java8提供的Lambda表達(dá)式過濾出所有拿鐵類的咖啡,并最終轉(zhuǎn)為Coffee[] 數(shù)組類型

2. 測試

main方法執(zhí)行拋出如下錯(cuò)誤提示

Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Lcom.wilson.algorithms.test.Coffee;
    at com.wilson.algorithms.test.TestCoffee.main(TestCoffee.java:30)

這里引出本文重點(diǎn):運(yùn)行時(shí)異常之類型轉(zhuǎn)換異常

ClassCastException

jdk1.0,開始提供該異常,此異常發(fā)生在程序代碼試圖將一個(gè)對(duì)象轉(zhuǎn)換為一個(gè)并非是自己或自己的子類對(duì)象的時(shí)候

舉個(gè)源碼中拋此異常的例子

// Integer類型
Object v = new Integer(0);

// 強(qiáng)制轉(zhuǎn)換為String類型
System.out.println((String) v);

因此我們總結(jié)一下,運(yùn)行時(shí)異常ClassCastException出現(xiàn)試圖將一個(gè)對(duì)象強(qiáng)制轉(zhuǎn)換為一個(gè)并非是自己或自己的子類對(duì)象的時(shí)候

至此回到我們文章開頭的問題,為什么我將Object[](實(shí)際里面的元素就是Coffee類型),強(qiáng)制轉(zhuǎn)為Coffee[]就會(huì)拋錯(cuò)呢?

  • 拋錯(cuò)分析
    實(shí)際上,在java中,Object是所有class類型數(shù)組當(dāng)然也是一種class類型,因此Object[]類型和Coffee[]類型都是Object類型的子類型
    但是對(duì)于Object[]類型和Coffee[]類型,二者同為數(shù)組類型,可他們之間并沒有什么父子關(guān)系,而是平級(jí)的關(guān)系
    正是因?yàn)楹芏嗤瑢W(xué)誤以為Object[]應(yīng)該是Coffee[]父類型,才會(huì)隨手寫出導(dǎo)致程序運(yùn)行時(shí)ClassCastException異常

  • 二者區(qū)別
    Object[]類型與Coffee[]類型的區(qū)別在于其數(shù)組中可以存放任意Object類型的對(duì)象,而Coffee[]則只能存放所有的Coffee類型(包括其子類)對(duì)象

  • 圖示


    關(guān)系圖示.png

總結(jié)

因此,對(duì)于日常開發(fā)中,我們應(yīng)該重視對(duì)Object[] 類型的返回值的處理,不能想當(dāng)然的認(rèn)為他就是Xxx[],隨手進(jìn)行強(qiáng)制類型轉(zhuǎn)換,而導(dǎo)致出現(xiàn)運(yùn)行時(shí)類型轉(zhuǎn)換異常

對(duì)于Lambda表達(dá)式的及早求值方法toArray(),Stream提供了一個(gè)重載的方法規(guī)避強(qiáng)制類型轉(zhuǎn)換異常的發(fā)生

<A> A[] toArray(IntFunction<A[]> generator);

我們改造一下文章開頭的代碼

Coffee[] lattes = coffees.stream()
                .filter(coffee -> coffee.getName().equals("latte"))
                .toArray(Coffee[]::new);

通過一個(gè)方法引用作為參數(shù),告知toArray方法,我想要返回的數(shù)組是一個(gè)Coffee[]類型

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 一、基礎(chǔ)知識(shí):1、JVM、JRE和JDK的區(qū)別:JVM(Java Virtual Machine):java虛擬機(jī)...
    殺小賊閱讀 2,548評(píng)論 0 4
  • 一、基本數(shù)據(jù)類型 注釋 單行注釋:// 區(qū)域注釋:/* */ 文檔注釋:/** */ 數(shù)值 對(duì)于byte類型而言...
    龍貓小爺閱讀 4,431評(píng)論 0 16
  • 對(duì)象的創(chuàng)建與銷毀 Item 1: 使用static工廠方法,而不是構(gòu)造函數(shù)創(chuàng)建對(duì)象:僅僅是創(chuàng)建對(duì)象的方法,并非Fa...
    孫小磊閱讀 2,177評(píng)論 0 3
  • 5繼承 5.1 類、超類和子類 重用部分代碼,并保留所有域?!癷s-a”關(guān)系,用extends表示。 已存在的類被...
    我快要上天啦閱讀 942評(píng)論 1 3
  • 父類與子類 在Java術(shù)語中,如果C1類擴(kuò)展自另一個(gè)類C2,我們稱C2為父類,也稱超類或基類,稱C1為子類,也稱次...
    Steven1997閱讀 1,319評(píng)論 1 2

友情鏈接更多精彩內(nèi)容