真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Java中對象的本質(zhì)是什么

本篇文章給大家分享的是有關(guān)Java中對象的本質(zhì)是什么,小編覺得挺實用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。

10年積累的成都網(wǎng)站建設(shè)、網(wǎng)站設(shè)計經(jīng)驗,可以快速應(yīng)對客戶對網(wǎng)站的新想法和需求。提供各種問題對應(yīng)的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡(luò)服務(wù)。我雖然不認識你,你也不認識我。但先做網(wǎng)站設(shè)計后付款的網(wǎng)站建設(shè)流程,更有新興免費網(wǎng)站建設(shè)讓你可以放心的選擇與我們合作。

1、抽象過程

    在學(xué)習(xí)編程語言中,除非是最底層的 0101001 這些東西,一定離不開類型(type)。什么是類型?類型就是“抽象的是什么”。

    “抽象的是什么”這句話,其實很容易理解,我們學(xué)習(xí)基礎(chǔ)數(shù)據(jù)類型時必會提到每種數(shù)據(jù)類型都占據(jù)多少多少個字節(jié),而且他們都是有范圍限制的,比如 byte 數(shù)據(jù)類型是8位、有符號的,以二進制補碼表示的整數(shù)——這其實就是通過給二進制數(shù)字人為的賦予定義來獲得一個固定的表示內(nèi)容來達到的,這個過程就是抽象:本來只是毫無意義的 0101001 這種東西,通過抽象,它能夠變成任意我們希望的東西。

    Java 中八大基本數(shù)據(jù)類型就是建立在多層抽象上的,而面向?qū)ο螅蠹叶颊f“萬物皆對象”,這句話的意思應(yīng)該是“萬物皆可被抽象后描述,而不僅僅限于一些基本的數(shù)據(jù)類型”,所以在 Java 中定義一個 class 時,我們給 class 賦予類型屬性和行為方法,通過這兩者抽象后形成的類(class)就是類型(type)的意思,他們幾乎可以等同看待。type 所抽象的東西還比較基本,所以說是基本數(shù)據(jù)類型。而 class 則全部都是對于外界事物的描述,對象則是某個類中的個體,每個個體都擁有相同的特征,所以他們屬于同一類(class)。所以類只是個概念,而對象才是一個個活蹦亂跳的可以使用操作的對象。

    創(chuàng)建一個類,就是創(chuàng)建新的數(shù)據(jù)類型。

    舉個例子暢想一下。int 是 Java 本身自帶的基本數(shù)據(jù)類型,它的描述是:32位、有符號的以二進制補碼表示的整數(shù),我們可以獲得一堆的整數(shù),它的類型是確定的,行為(運算)也被限定,帶有正負等。Java 中也定義了一個 Integer 的 class,這個 Integer 跟 int 有什么關(guān)聯(lián)嗎?當(dāng)然,它被設(shè)計來對應(yīng)于基本數(shù)據(jù)類型 int,并且定義了很多操作方法。所以,如果忽略 int 類型的存在的話,Integer 類完全就是一種數(shù)據(jù)類型,而且還是一種“升級版”的。

2、封裝性

    封裝性很容易理解,就是把一堆東西用大括號包起來。封裝性作為面向?qū)ο蟮娜筇匦灾?,深層意義絕不僅限于這個淺顯的概念。

    上面說到類與類型,類型就是“抽象的是什么”。類呢?就是“對萬物的抽象后封裝其描述”。所以我在上面總結(jié)說:創(chuàng)建一個類,就是創(chuàng)建新的數(shù)據(jù)類型。

    封裝了什么描述呢?每個類中的成員變量都是對這個類抽象后的描述。

    比方說,我要創(chuàng)建一個類:人,那么我覺得人應(yīng)該要有名字、性別。如果實際情況不需要知道或用到其他的屬性,我就不會創(chuàng)建其他的成員變量來描述“人”這個類,而只有兩個成員變量。抽象就是:我只描述我想要的。

    抽象了一個類(型)之后,在 Java 里就是用花括號包起來,就封裝成了一個真正的類(型概念)。

    封裝性是面向?qū)ο蟮淖罨镜奶匦浴?/p>

3、繼承

    同上面一樣,繼承的概念我也不想多說,只是說一些我認為起到點睛效果的點。

    在 Java 里的繼承不是真正意義上的或者純概念上的繼承,它是通過讓派生類獲得基類的一個子對象來獲得看起來是繼承的樣子(效果)的。這個子對象等同于我們手動 new 一個對象,這就是為什么我們在寫每一個派生類的任意構(gòu)造函數(shù)時都需要確保能夠調(diào)用到基類的任一個構(gòu)造函數(shù)且只能調(diào)用一個構(gòu)造函數(shù)的原因。

    ——這句話有點拗口,但是不難理解,這也是考察Java基礎(chǔ)時??嫉降闹R點——給出幾個類你,他們之間有繼承關(guān)系,問你編譯運行后的輸出結(jié)果是什么,通常結(jié)果都是發(fā)生編譯時異常,因為代碼中往往會通過很隱秘的方法讓派生類最終并不能調(diào)用到基類的構(gòu)造函數(shù),這樣的結(jié)果就是派生類沒辦法生成并獲取基類的子對象,那么繼承所必需的代碼就不完整,自然就在編譯的時候就發(fā)生異常了。

    理解這一點之后發(fā)現(xiàn),所謂的繼承其實可以通過手動的方式完成幾乎相同(并不完全相同)的效果,你肯定猜到了,那就是直接 new 另一個類的對象,讓它成為自己的類的成員變量——你一定經(jīng)常這樣做。這樣的結(jié)果就是,你獲得那個類的全部訪問權(quán)限允許的屬性和方法。

    常常有人出這樣的題目來嚇唬人,就是有繼承關(guān)系的兩個類,基類有個私有變量a(String型),派生類能不能使用基類的a變量?答案肯定是不能的,系統(tǒng)提示沒有訪問權(quán)限。如果是真的概念上的繼承的話,派生類應(yīng)該獲得基類的所有元素才對啊,為什么說沒有權(quán)限呢?原因也是上述的:這僅僅是通過new一個類的對象來訪問而已,自然是不能直接操作對象的聲明為私有的任何東西的。

    真正的繼承,當(dāng)然就是說所有東西都是屬于派生類才對的。

    假設(shè)這時候子類也有一個私有變量a(String型)。能不能訪問到呢?這兩個變量是什么關(guān)系呢?這時候變成可以訪問了,因為他們都是分別屬于兩個類的成員變量,互相獨立,他們之間沒有任何的關(guān)系,這時候其實就是訪問自己的私有變量,當(dāng)然沒有問題了。

    所以說手動的、直接 new 一個對象,也是一種“繼承”,這種方式反而更加靈活方便,它有個專門的名詞叫做“組合”。組合與繼承之間糾纏著的愛恨情仇大抵如上。同時,在寫代碼的時候,通常是優(yōu)先使用組合而不是繼承。

    那么什么時候使用繼承呢?繼承雖然相比組合來說比較笨重不靈活(比如不能多繼承可以多組合等),但是繼承的魅力還是不小的,比如多態(tài)等。所以當(dāng)你覺得派生類有向上(基類)轉(zhuǎn)型的必要時,使用繼承。

4、多態(tài)

    多態(tài)依賴于繼承,組合是沒辦法完成多態(tài)的,這就是優(yōu)缺點——有得必有失,看你的取舍。

    多態(tài)的概念也不多說,因為這文章并不是知識普及用的,是思想提升用的,如果連相關(guān)知識點都沒有掌握的話,估計你也不會看到這里了。

    多態(tài)有個類型轉(zhuǎn)換的問題:向上轉(zhuǎn)型和向下轉(zhuǎn)型。向上轉(zhuǎn)型是永遠不會出錯的,同時意味著派生類丟失基類并沒有的部分信息。而向下轉(zhuǎn)型原則上是不允許的或者是不建議的,隨意的、直接的向下轉(zhuǎn)型,在編譯器就會報錯。如果確實有需要,則需要強制轉(zhuǎn)型:所以在 Java 里所有的向下轉(zhuǎn)型都必須顯式聲明,當(dāng)顯式聲明時,就意味著你已經(jīng)了解這種風(fēng)險并愿意承擔(dān)其帶來的問題等。

    這里有個問題:為什么向上轉(zhuǎn)型是安全的,向下轉(zhuǎn)型則是危險的?如果你把它當(dāng)作一個知識點去學(xué)習(xí)并記住了,那么你為什么不會好奇其背后的緣由呢?這里就想回答這個背后的原因。

    上面說繼承的時候說過,Java 中的繼承并不是我們概念上所理解的真正的繼承,如果子類繼承了父類,那么當(dāng)你 new 了一個子類對象時,其實在 Java 的底層會同時幫你 new 一個父類的對象作為子類的子對象,這時候在Java里想要向上轉(zhuǎn)型時,通過這個父類的子對象很容易就知道了這個繼承關(guān)系,轉(zhuǎn)型自然是安全的。

    而如果 new 了的是父對象,再向下轉(zhuǎn)型成子對象時,這樣在編譯期就會發(fā)生異?!狫ava 里是不允許這樣的隨意向下轉(zhuǎn)型的行為的。所以你需要在父對象的前面顯式聲明說:我要強制轉(zhuǎn)型。編譯器才能通過編譯。

    但是,在上面這種情況,即使你在轉(zhuǎn)換的時候已經(jīng)在前面的小括號里聲明了類型來強制轉(zhuǎn)型,讓自己的代碼在編譯時能夠通過了,運行時還是會出現(xiàn)異常的:ClassCastException,因為這時候JVM發(fā)現(xiàn)這個父對象根本沒有任何強轉(zhuǎn)類型(子類)的信息。為了避免這種運行時異常通常需要去確認一下是不是同一個類型:instanceof 判斷通過后再進行轉(zhuǎn)換,就能確保代碼不會出現(xiàn)異常。

    有一種向下轉(zhuǎn)型不會出現(xiàn)運行時異常 ClassCastException 的情況,那就是一開始 new 的是子類的對象,然后賦值給一個父類的引用,然后再將這個父類引用的對象強制轉(zhuǎn)型為子類對象,這時候的強轉(zhuǎn)是成功的——這背后的原因也很容易理解:new 創(chuàng)建的所有對象都是存放在堆內(nèi)存區(qū)的,而引用則存放在棧內(nèi)存區(qū),它保存的只是堆內(nèi)存中那個對象的開始地址而已。因為一開始 new 的就是子類的對象,所以這個對象是不僅擁有父類的子對象,而且擁有自身的對象的。這時候它不管是向上轉(zhuǎn)型還是向下強制轉(zhuǎn)型,都是不會有問題的。

    下面是一個相似的例子:

    第25行代碼會在運行時拋出ClassCastException,java.lang.Integer cannot be cast to java.lang.Double。這兩個類都繼承自Number抽象類,所以他們的向上轉(zhuǎn)型都不會有任何問題并且不需要強轉(zhuǎn),但是向上轉(zhuǎn)型后再向下轉(zhuǎn)型時,拋出的異常依然能識別到創(chuàng)建對象時的類,強轉(zhuǎn)是失敗的。

        Java中對象的本質(zhì)是什么

    這就是為什么非要做類型判斷后才能進行強轉(zhuǎn),所以注釋掉的28到33行代碼才是正確的做法。

    同時,在Java里有個 Class 類,JVM 每加載一個類,Class 類都會新建一個對象,用于記錄它的類型信息,Java 的反射機制也是基于它。

以上就是Java中對象的本質(zhì)是什么,小編相信有部分知識點可能是我們?nèi)粘9ぷ鲿姷交蛴玫降?。希望你能通過這篇文章學(xué)到更多知識。更多詳情敬請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。


名稱欄目:Java中對象的本質(zhì)是什么
分享地址:http://weahome.cn/article/jjjspj.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部