Java強制轉(zhuǎn)化示例代碼詳解
引入
在Java編程語言中,類型轉(zhuǎn)換(無論是強制類型轉(zhuǎn)換還是自動類型轉(zhuǎn)換)的方向并不是簡單地基于“高位”和“低位”的概念,而是基于數(shù)據(jù)類型的范圍和精度。
基本類型強制轉(zhuǎn)換
1.數(shù)字之間
short s = 100; int i = s; // 自動類型轉(zhuǎn)換,安全 int j = 30000; // 一個大于short類型能表示的最大值的int short k = (short) j; // 強制類型轉(zhuǎn)換,可能導(dǎo)致數(shù)據(jù)丟失
上面給出了兩種數(shù)值轉(zhuǎn)換的概念,第一種是short轉(zhuǎn)成int類型,由于short是16位的,int是32位的,此時就是低精度轉(zhuǎn)為高精度,所以編譯器會自動進行類型轉(zhuǎn)換,是安全的,不用強轉(zhuǎn)(因為這種轉(zhuǎn)換是安全的,不會丟失任何信息,只是簡單地擴展了符號位)
而第二種則是讓int類型轉(zhuǎn)成short,高精度轉(zhuǎn)低精度,不安全,強制類型轉(zhuǎn)換,short只能存儲低16位的數(shù)據(jù),高16位的位置就舍棄了,所但凡int的高16位存有數(shù)據(jù),此時的強轉(zhuǎn)就會發(fā)生數(shù)據(jù)丟失。
所以通常而言,這種高精度強轉(zhuǎn)低精度是沒有意義的。
2.數(shù)字字符之間
引入
以前有涉及過steam,buffer的概念,并且它們本質(zhì)都是數(shù)組。
int c=23456; char d=(char) c; //將int類型的c強轉(zhuǎn)成char類型的d System.out.println(d); //并且能夠解析輸出
steam就是類似如下的一串二進制數(shù)字,在解析時以8位或32位等解析成十進制,就可以得到不同的結(jié)果:
int[] arr={23456,23457,34567,23876,32447}; for(int x:arr){//解析輸出 char e=(char) x; System.out.println(e); }
【以上就是兩個基本類型強制轉(zhuǎn)換的例子,而且基本類型之間都可以進行強轉(zhuǎn),只是有的沒有意義?!?/p>
引用類型的強制轉(zhuǎn)換
引入多態(tài)概念前提
e.g.首先,我們定義一個父類
Animal
,并在其中聲明一個方法makeSound
,但不在父類中實現(xiàn)它(可以將它設(shè)為抽象方法,但在這個例子中,我們?yōu)榱撕喕?,讓它返回一個默認字符串)。然后,我們創(chuàng)建兩個子類Dog
和Cat
,它們都繼承自Animal
類,并各自實現(xiàn)了makeSound
方法。
// 父類 Animal class Animal { // 可以是一個抽象方法,但這里為了簡化,我們提供一個默認實現(xiàn) public String makeSound() { return "Some generic animal sound"; } } // 子類 Dog 繼承自 Animal class Dog extends Animal { @Override public String makeSound() { return "Woof! Woof!"; } } // 子類 Cat 繼承自 Animal class Cat extends Animal { @Override public String makeSound() { return "Meow! Meow!"; } } public class PolymorphismExample { public static void main(String[] args) { // 使用父類類型的引用來指向子類對象 Animal myDog = new Dog(); Animal myCat = new Cat(); // 調(diào)用被重寫的方法,將展示多態(tài)性 System.out.println(myDog.makeSound()); // 輸出: Woof! Woof! System.out.println(myCat.makeSound()); // 輸出: Meow! Meow! // 盡管 myDog 和 myCat 都是 Animal 類型的引用, // 但它們實際上指向的是 Dog 和 Cat 對象, // 因此調(diào)用 makeSound 方法時會執(zhí)行子類中的實現(xiàn)。 } }
在這個例子中,展示了多態(tài)性的兩個關(guān)鍵方面:
父類引用指向子類對象:
myDog
是一個Animal
類型的引用,但它實際上指向了一個Dog
對象。同樣,myCat
是一個Animal
類型的引用,但它指向了一個Cat
對象。方法重寫:
Dog
和Cat
類都重寫了Animal
類中的makeSound
方法。因此,當通過myDog
和myCat
引用調(diào)用makeSound
方法時,會分別調(diào)用Dog
和Cat
類中的實現(xiàn)。以上例子展示了多態(tài)所遵守的兩項,下面是完整的多態(tài)遵循條件:
要符合多態(tài),通常需要滿足以下幾個條件:
繼承:多態(tài)通常依賴于繼承關(guān)系。在面向?qū)ο缶幊讨?,子類繼承父類,從而可以重用父類的代碼并擴展新的功能。多態(tài)性允許我們使用父類類型的引用來引用子類對象。
方法重寫(Override):子類需要重寫父類中的某些方法,以便在調(diào)用這些方法時能夠表現(xiàn)出不同的行為。方法重寫是多態(tài)性的關(guān)鍵所在,它允許子類提供父類方法的具體實現(xiàn)。
父類引用指向子類對象:這是多態(tài)性的另一個重要方面。我們可以創(chuàng)建一個父類類型的引用,并將其指向一個子類對象。當通過這個引用調(diào)用一個被重寫的方法時,將調(diào)用子類中的該方法實現(xiàn),而不是父類中的實現(xiàn)。
接口或抽象類:雖然多態(tài)性不一定需要接口或抽象類,但它們?yōu)槎鄳B(tài)性提供了強大的支持。接口和抽象類可以定義方法簽名,而不提供具體實現(xiàn)。子類可以實現(xiàn)這些接口或繼承這些抽象類,并提供具體的方法實現(xiàn)。這樣,當使用接口或抽象類類型的引用來引用子類對象時,就可以實現(xiàn)多態(tài)性。
運行時類型識別(RTTI, Run-Time Type Identification):在Java等語言中,運行時類型識別是多態(tài)性的基礎(chǔ)之一。它允許程序在運行時確定對象的實際類型,并根據(jù)這個類型來調(diào)用相應(yīng)的方法。這是通過方法重寫和父類引用指向子類對象來實現(xiàn)的。
【注意:雖然給出了這么多條件,但是多態(tài)性的核心在于方法重寫和父類引用指向子類對象(句柄可以指向自己類的對象或者自己的子孫后代類的對象)這兩個方面。】
【注意:引用類型之間的強制類型轉(zhuǎn)換就沒有這么自由了,會有諸多限制】
如下兩個子類繼承Person父類:
【注意:遵循一個類的句柄可以指向自己類的對象或者自己的子孫后代類的對象】
所以以下兩種表達方式是錯誤的:
①直接報錯:
②運行時報錯:
運行時報錯是因為不符合多態(tài),即“指向自己類的對象或者自己的子孫后代類的對象”,這里表示的是:
將s(指向Child2
實例的Person
類型變量)強轉(zhuǎn)換成Child 3,Child2和Child3是兄弟關(guān)系,不符合多態(tài)。
如何解決以下問題呢?(o ∀ o )
有啦??!就用那招!(?∀?(?∀?*)
引入關(guān)鍵字instanceof:
instanceof
是一個用于檢查對象是否為特定類或其任何父類的實例的關(guān)鍵字。這個操作符返回一個布爾值:如果對象是指定類的實例,或者是該類的任何子類的實例,則返回true
;否則返回false
。if (object instanceof ClassName) { // 對象是指定類的實例或其子類的實例時執(zhí)行的代碼 }其中:
object
是要檢查的對象ClassName
是要檢查的類名(包括接口名)還不理解沒關(guān)系,以下給出一個實例:
class Animal {} class Dog extends Animal {} class Cat extends Animal {} public class Main { public static void main(String[] args) { Animal myDog = new Dog(); //Animal myDog = new Dog(); 創(chuàng)建了一個 Dog 類的實例,并將其引用賦值給 Animal 類型的變量 myDog。這意味著 myDog 指向的是一個 Dog 對象,但它在編譯時被視為 Animal 類型。 Animal myCat = new Cat(); // Animal myCat = new Cat(); 類似地,創(chuàng)建了一個 Cat 類的實例,并將其引用賦值給 Animal 類型的變量 myCat。 System.out.println(myDog instanceof Dog); // 輸出 true System.out.println(myDog instanceof Animal); // 輸出 true System.out.println(myDog instanceof Cat); // 輸出 false System.out.println(myDog instanceof Object); // 輸出 true System.out.println(null instanceof Animal); // 輸出 false } }
在這個示例中,
myDog
是Dog
類的實例,也是Animal
類和Object
類的實例(因為所有類都繼承自Object
)。因此,myDog instanceof Dog
返回true
,myDog instanceof Animal
也返回true
,但myDog instanceof Cat
返回false
,因為myDog
不是Cat
的實例。同樣地,null
不是任何類的實例,所以null instanceof Animal
返回false
。
public class Test{ public static void main(String[] mmm) throws Exception{ Child2 x=new Child2(); //Child2 x = new Child2(); 創(chuàng)建了一個 Child2 類的實例,并將其引用賦值給 Child2 類型的變量 x。 Child3 w=new Child3(); //Child3 w = new Child3(); 創(chuàng)建了一個 Child3 類的實例,并將其引用賦值給 Child3 類型的變量 w。 //句柄可以指向自己類的對象或者自己的子孫后代類的對象 Person s=x; //父類指子類child2 m1(s); s=w; m1(s); public static void m1(Person s){ Child3 w=null; if(s instanceof Child3){ //?使用instanceof關(guān)鍵字檢查s是否是Child3的實例,如果是true,才進行下面的強轉(zhuǎn)代碼 //?用instanceof來驗證強轉(zhuǎn)? w=(Child3) s; } } } }
可以看見上面對m1() 方法進行了兩次調(diào)用。
如果 s
指向的是 Child3
實例(在第二次調(diào)用 m1(s);
時),條件為真,代碼塊內(nèi)的強轉(zhuǎn)類型轉(zhuǎn)換 w = (Child3) s;
會執(zhí)行。如果 s
指向的是 Child2
實例(在第一次調(diào)用 m1(s);
時),條件為假,代碼塊內(nèi)的代碼不會執(zhí)行。
總結(jié)
到此這篇關(guān)于Java強制轉(zhuǎn)化的文章就介紹到這了,更多相關(guān)Java強制轉(zhuǎn)化內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java讀取配置文件自定義字段(yml、properties)
本文主要介紹了java讀取配置文件自定義字段(yml、properties),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07java基礎(chǔ)理論Stream的Filter與謂詞邏輯
這篇文章主要為大家介紹了java基礎(chǔ)理論Stream的Filter與謂詞邏輯,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-03-03Spring中@Autowired和@Resource注解的使用區(qū)別詳解
這篇文章主要介紹了Spring中@Autowired和@Resource注解的使用區(qū)別詳解,@Autowired默認根據(jù)type進行注入,找到與指定類型兼容的?Bean?并進行注入,如果無法通過type匹配到對應(yīng)的?Bean?的話,會根據(jù)name進行匹配,如果都匹配不到則拋出異常,需要的朋友可以參考下2023-11-11springboot項目同時啟動web服務(wù)和grpc服務(wù)的方法
本文主要介紹了springboot項目同時啟動web服務(wù)和grpc服務(wù)的方法,通過實際代碼示例展示了實現(xiàn),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-02-02java 父類子類有同名方法時如何調(diào)用的實現(xiàn)
這篇文章主要介紹了java 父類子類有同名方法時如何調(diào)用的實現(xiàn),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-09-09