Java 之類型轉(zhuǎn)換與多態(tài)詳情
一、類型檢查
Java的任意變量和引用經(jīng)過類型聲明
(type declaration
),才能使用。我們之前見過對象數(shù)據(jù)、類數(shù)據(jù)、方法參數(shù)、方法返回值以及方法內(nèi)部的自動變量,它們都需要聲明其類型。Java是一種強(qiáng)類型
(strongly typing
)語言,它會對類型進(jìn)行檢查。如果我們錯誤的使用類型,將造成錯誤。
比如在下面的Test類
中,我們將一個Cup類
對象賦予給aPerson類
引用:
public class Test { public static void main(String[] args) { Human aPerson; aPerson = new Cup(); } } class Human { /** * constructor */ public Human(int h) { this.height = h; } /** * accessor */ public int getHeight() { return this.height; } /** * mutator */ public void growHeight(int h) { this.height = this.height + h; } private int height; } class Cup { public void addWater(int w) { this.water = this.water + w; } public void drinkWater(int w) { this.water = this.water - w; } private int water = 0; }
javac將返回:
found : Cup required: Human aPerson = new Cup(); ^ 1 error
二、基本類型轉(zhuǎn)換
Java可以對基本類型的變量進(jìn)行類型轉(zhuǎn)換。不同的基本類型有不同的長度和存儲范圍。如果我們從一個高精度類型轉(zhuǎn)換到低精度類型,比如從float
轉(zhuǎn)換到int
,那么我們有可能會損失信息。這樣的轉(zhuǎn)換叫做收縮變換(narrowing conversion
)。這種情況下,我們需要顯示的聲明類型轉(zhuǎn)換,比如:
public class Test { public static void main(String[] args) { int a; a = (int) 1.23; // narrowing conversion System.out.println(a); } }
如果我們從低精度類型轉(zhuǎn)換成高精度類型,則不存在信息損失的顧慮。這樣的變換叫做寬松變換(widening conversion
)。我們不需要顯示的要求類型轉(zhuǎn)換,Java
可以自動進(jìn)行:
public class Test { public static void main(String[] args) { int a = 3; double b; b = a; // widening conversion System.out.println(a); } }
基本類型轉(zhuǎn)換流程圖:
三、upcast與多態(tài)
在Java中,引用也可以進(jìn)行類型轉(zhuǎn)換,但是有限制。
我們可以將一個衍生類引用轉(zhuǎn)換為其基類引用,這叫做向上轉(zhuǎn)換(upcast
)或者寬松轉(zhuǎn)換。下面的BrokenCup
類繼承自Cup
類,并覆蓋了Cup類
中原有的addWater
()和drinkWater
()方法:
public class Test { public static void main(String[] args) { Cup aCup; BrokenCup aBrokenCup = new BrokenCup(); aCup = aBrokenCup; // upcast aCup.addWater(10); // method binding } } class Cup { public void addWater(int w) { this.water = this.water + w; } public void drinkWater(int w) { this.water = this.water - w; } private int water = 0; } class BrokenCup extends Cup { public void addWater(int w) { System.out.println("shit, broken cup"); } public void drinkWater(int w) { System.out.println("om...num..., no water inside"); } }
程序運行結(jié)果:
shit, broken cup
在上面可以看到,不需要任何顯示說明,我們將衍生類引用aBrokenCup賦予給它的基類引用aCup。類型轉(zhuǎn)換將由Java自動進(jìn)行。
我們隨后調(diào)用了aCup
(我們聲明它為Cup
類型)的addWater()
方法。盡管aCup
是Cup
類型的引用,它實際上調(diào)用的是BrokenCup
的addWater()
方法!也就是說,即使我們經(jīng)過upcast
,將引用的類型寬松為其基類,Java
依然能正確的識別對象本身的類型,并調(diào)用正確的方法。Java
可以根據(jù)當(dāng)前狀況,識別對象的真實類型,這叫做多態(tài)(polymorphism
)。多態(tài)是面向?qū)ο蟮囊粋€重要方面。
多態(tài)是Java
的支持的一種機(jī)制,同時也是面向?qū)ο蟮囊粋€重要概念。這提出了一個分類學(xué)的問題,既子類對象實際上“是”父類對象。比如一只鳥,也是一個動物;一輛汽車,也必然是一個交通工具。Java
告訴我們,一個衍生類對象可以當(dāng)做一個基類對象使用,而Java
會正確的處理這種情況。
比如下面的繼承關(guān)系:
我們可以說用杯子(Cup
)喝水(drinkWater
)。實際上,喝水這個動作具體含義會在衍生類中發(fā)生很大變換。比如用吸管喝水,和從一個破杯子喝水,這兩個動作差別會很大,雖然我們抽象中都講“喝水”。我們當(dāng)然可以針對每個衍生類分別編程,調(diào)用不同的drinkWater
方法。然而,作為程序員,我們可以對杯子編程,調(diào)用Cup
的drinkWater
()方法,而無論這個杯子是什么樣的衍生類杯子。Java
會調(diào)用相應(yīng)的正確方法,正如我們在上面程序中看到的。
看一個更加有意義的例子,我們給Human
類增加一個drink()
方法,這個方法接收一個杯子對象和一個整數(shù)作為參數(shù)。整數(shù)表示喝水的水量:
public class Test { public static void main(String[] args) { Human guest = new Human(); BrokenCup hisCup = new BrokenCup(); guest.drink(hisCup, 10); } } class Human { void drink(Cup aCup, int w) { aCup.drinkWater(w); } }
程序運行結(jié)果:
shit, no water inside
我們在Human
類的drink()
的定義中,要求第一個參量為Cup類型
的引用。但在實際運用時(Test類
),將Cup
的BrokenCup
衍生類對象。這實際上是將hisCup
向上轉(zhuǎn)型稱為Cup類
,傳遞給drink()方法
。在方法中,我們調(diào)用了drinkWater()方法
。Java發(fā)現(xiàn)這個對象實際上是BrokenCup
對象,所以實際調(diào)用了BrokenCup
的相應(yīng)方法。
四、downcast
我們可以將一個基類引用向下轉(zhuǎn)型(downcast
)成為衍生類的引用,但要求該基類引用所指向的對象,已經(jīng)是所要downcast的衍生類對象
。比如可以將上面的hisCup
向上轉(zhuǎn)型為Cup
類引用后,再向下轉(zhuǎn)型成為BrokenCup
類引用。
五、Object類型
Java中,所有的類實際上都有一個共同的繼承祖先
,即Object類
。Object類
提供了一些方法,比如toString()。
我們可以在自己的類定義中覆蓋這些方法。
Object: 祖先
我們可以編寫一個操作Object對象的程序,就可以通過upcast,將任意對象傳遞給該程序。
我將在以后深入Object類
多態(tài)的實現(xiàn)是依靠RTTI的支持
到此這篇關(guān)于Java 之類型轉(zhuǎn)換與多態(tài)詳情的文章就介紹到這了,更多相關(guān)Java 之類型轉(zhuǎn)換與多態(tài)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Java多態(tài)性抽象類與接口細(xì)致詳解
- Java面向?qū)ο蠡A(chǔ)之多態(tài)性,抽象類和接口
- Java抽象類、繼承及多態(tài)和適配器的實現(xiàn)代碼
- JAVA回顧:封裝,繼承,多態(tài)
- 一篇文章帶你了解Java基礎(chǔ)-多態(tài)
- Java多態(tài)到底都有啥好處
- Java基礎(chǔ)之面向?qū)ο髾C(jī)制(多態(tài)、繼承)底層實現(xiàn)
- Java單例模式繼承覆蓋多態(tài)原理詳解
- Java面向?qū)ο笕筇匦约岸鄳B(tài)解析
- Java必須學(xué)會的類的繼承與多態(tài)
- Java語法之 Java 的多態(tài)、抽象類和接口
相關(guān)文章
springboot中@Async默認(rèn)線程池導(dǎo)致OOM問題
這篇文章主要介紹了springboot中@Async默認(rèn)線程池導(dǎo)致OOM問題,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06java jackson 將對象轉(zhuǎn)json時,忽略子對象的某個屬性操作
這篇文章主要介紹了java jackson 將對象轉(zhuǎn)json時,忽略子對象的某個屬性操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-10-10

@JsonSerialize(using = LongToStringUtil.class)注解的使

詳解關(guān)于eclipse中使用jdk15對應(yīng)javafx15的配置問題總結(jié)