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