精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Java 面向?qū)ο笠挥[

開發(fā) 后端
學 Java 的朋友都知道,Java 是一門典型的面向?qū)ο蟮母呒壋绦蛟O計語言,但有些朋友可能不清楚面向?qū)ο笤?Java 中是怎么體現(xiàn)的。這篇文章就向大家分享下 Java 在面向?qū)ο蠓矫娴囊恍┲R。

[[404430]]

本文轉(zhuǎn)載自微信公眾號「蝸牛互聯(lián)網(wǎng)」,作者白色蝸牛。轉(zhuǎn)載本文請聯(lián)系蝸牛互聯(lián)網(wǎng)公眾號。

本文大綱:

前言

學 Java 的朋友都知道,Java 是一門典型的面向?qū)ο蟮母呒壋绦蛟O計語言,但有些朋友可能不清楚面向?qū)ο笤?Java 中是怎么體現(xiàn)的。這篇文章就向大家分享下 Java 在面向?qū)ο蠓矫娴囊恍┲R。

Java 語言簡介

Java 語言特點

首先我們看下 Java 的語言特點,如圖所示。

Java 是純粹的面向?qū)ο笳Z言,它因統(tǒng)一的字節(jié)碼文件和差異化的 JDK 而具有平臺無關(guān)的特性。

Java 內(nèi)置豐富的類庫,使開發(fā)者效率大為提升。它支持 web,廣泛應用于各大互聯(lián)網(wǎng)企業(yè)的網(wǎng)站后臺,像阿里美團都在使用。

Java 的安全性也很出眾,通過沙箱安全模型保證其安全性,能夠有效防止代碼攻擊。

Java 也具備很強的健壯性,比如它是強類型的,支持自動化的垃圾回收器,有完善的異常處理機制和安全檢查機制。

與 C++ 比較

比較點 C++ Java
語言類型 編譯型語言 解釋編譯混合型語言
執(zhí)行速度
是否跨平臺
面向?qū)ο?/td> 面向?qū)ο蠛兔嫦蜻^程混合 純面向?qū)ο?/td>
指針
多繼承 支持 不支持
內(nèi)存管理 手動 自動

從語言類型上看,C++ 的代碼編譯好,就能被計算機直接執(zhí)行,它是編譯型語言,而 Java 經(jīng)過 javac 把 java 文件編譯成 class 文件后,還需要 JVM 從 class 文件讀一行解釋執(zhí)行一行,它是解釋編譯混合型語言。也就是中間多了 JVM 這一道,Java 也具備了跨平臺特性,而 C++ 就沒有這個優(yōu)勢。

從面向?qū)ο蟮慕嵌壬峡矗珻++ 是在 C 的基礎上的新的探索和延伸,因此它是面向?qū)ο蠛兔嫦蜻^程混合的,而 Java 就是純粹的面向?qū)ο蟆?/p>

此外,C++ 有指針的概念,Java 沒有。C++ 支持多繼承,Java 不支持。C++ 需要手動進行內(nèi)存管理,Java 通過垃圾回收機制實現(xiàn)了內(nèi)存的自動管理。

面向?qū)ο笏枷?/h2>

我們總在提面向?qū)ο螅敲嫦驅(qū)ο缶烤故莻€什么東西呢?在面向?qū)ο蟪霈F(xiàn)之前的面向過程又是怎么回事呢?

其實無論是面向?qū)ο筮€是面向過程,都是我們在編程時解決問題的一種思維方式。

只是在最初,人們分析解決問題的時候,會把所需要的步驟都列出來,然后通過計算機中的函數(shù)把這些步驟挨個實現(xiàn),這種過程化的敘事思維,就是面向過程思想。

你比如,把一頭大象放進冰箱,通常會怎么做呢?

我們的習慣性思維是會分為三步,第一步,把冰箱門打開,第二步,把大象推進去,第三步,把冰箱門關(guān)閉(假設大象很乖,冰箱很大,門能關(guān)住)。

這種方式固然可行,但當場景發(fā)生變化時,比如大象變成豬,冰箱變成衣柜,類似的步驟用面向過程編碼的話就要再寫一遍。這樣就導致代碼開發(fā)變成了記流水賬,久而久之就成為面條代碼。

我們仔細分析面向過程的這些步驟,會發(fā)現(xiàn)都是命令式的動賓結(jié)構(gòu):開冰箱門,推大象,場景切換下就是開衣柜門,推豬。你會發(fā)現(xiàn)從這兩種場景下是可以找到共性的,就是冰箱門和衣柜門都有打開和關(guān)閉的特點,大象和豬都能走路,所以能被人推進去。

當我們的視角不再是流程,而是操作對象的時候,冰箱門和衣柜門都可以抽象成門,有打開和關(guān)閉的特點,大象和豬都可以抽象成動物,有走路的特點。按這個思路,我們可以把這件事簡化成主謂結(jié)構(gòu):門打開,動物走進去,門關(guān)閉。

這種把事情分解成各個對象,描述對象在整個事情中的行為,就是面向?qū)ο笏枷搿?/p>

你會發(fā)現(xiàn),面向過程更講事情的步驟,面向?qū)ο蟾v對象的行為。

面向?qū)ο罂梢曰趯ο蟮墓残宰龀橄螅瑸檐浖こ痰膹陀煤蛿U展打好了堅實的基礎。這也是為什么在很多大型軟件開發(fā)選型上,大多會使用面向?qū)ο笳Z言編程。

面向?qū)ο蠡A

Java 作為純面向?qū)ο笳Z言,我們有必要了解下面向?qū)ο蟮幕A知識。

面向?qū)ο笥兴拇筇卣鳎浅橄螅庋b,繼承和多態(tài)。也有很多人認為是三大特征,不包括抽象,但我覺得抽象才是面向?qū)ο笏枷胱顬楹诵牡奶卣鳎渌齻€特征無非是抽象這個特征的實現(xiàn)或擴展。

我總結(jié)了下這四大特征在面向?qū)ο箢I域分別解決了什么問題,再逐一介紹:

  • 抽象:解決了模型的定義問題。
  • 封裝:解決了數(shù)據(jù)的安全問題。
  • 繼承:解決了代碼的重用問題。
  • 多態(tài):解決了程序的擴展問題。

抽象

抽象是面向?qū)ο蟮暮诵奶卣鳎己玫臉I(yè)務抽象和建模分析能力是后續(xù)封裝、繼承和多態(tài)的基礎。

面向?qū)ο笏季S中的抽象分為歸納和演繹兩種。

歸納是從具體到本質(zhì),從個性到共性,將一類對象的共同特征進行歸一化的邏輯思維過程。比如我們把見到的像大象,老虎,豬這些能動的有生命的對象,歸納成動物。

演繹是從本質(zhì)到具體,從共性到個性,將對象逐步形象化的過程。比如從生物到動物,從動物到鳥類。演繹的結(jié)果不一定是具體的對象,也可以是像鳥類這種抽象結(jié)果,因此演繹仍然是抽象思維,而非具象思維。

Java 中的 Object 類是任何類的默認父類,是對萬物的抽象。這就是我們常說的:萬物皆對象。

看一看 java.lang.Object 類的源碼,我們基本能看到 Java 世界里對象的共同特征。

getClass() 說明了對象是誰,toString() 是對象的名片,clone() 是繁殖對象的方式, finalize() 是銷毀對象的方式,hashCode() 和 equals() 是判斷當前對象與其他對象是否相等的方式,wait() 和 notify() 是對象間通信與協(xié)作的方式。

類的定義

除了 JDK 中提供的類之外,我們也可以基于自己業(yè)務場景的抽象定義類。

我們看下 Java 語法中的 class(類)是怎么構(gòu)成的。

以下是概覽圖,我們按圖介紹。

我們先關(guān)注圖中的黃色區(qū)塊,在 Java 里就叫 class(類)。

好比一個事物有屬性和能力一樣,比如人有名字,人能吃飯。對應到 Java class 里就是變量和方法,即紅色區(qū)塊和紫色區(qū)塊。

變量分為成員變量,靜態(tài)變量和局部變量三種,方法分為構(gòu)造方法、實例方法和靜態(tài)方法三種。

我們舉個例子來說明下,假設全世界的面包數(shù)量就 100 個,并且生產(chǎn)已經(jīng)停滯,而且只有蝸牛和小白兩個人能吃到,我們就可以按以下的代碼來描述這兩個人吃面包的過程以及面包的情況。

  1. package cn.java4u.oo; 
  2.  
  3.  
  4. /** 
  5.  * @author 蝸牛 
  6.  * @from 公眾號:蝸牛互聯(lián)網(wǎng) 
  7.  */ 
  8. public class Person { 
  9.  
  10.     /** 
  11.      * [成員變量]需要被實例化后使用,每個實例都有獨立空間,通過 對象.成員變量名 訪問 
  12.      * 名字 
  13.      */ 
  14.     String name
  15.  
  16.  
  17.     /** 
  18.      * [靜態(tài)變量]用 static 修飾,無需實例化即可使用,每個實例共享同一個空間,通過 類名.靜態(tài)變量名 訪問 
  19.      * 面包數(shù)量 
  20.      */ 
  21.     static int breadNum; 
  22.  
  23.     /** 
  24.      * [方法] 
  25.      * 吃一個面包 
  26.      * 
  27.      * @param num 方法入?yún)ⅲ悦姘膫€數(shù) 
  28.      */ 
  29.     void eatBread(int num) { 
  30.  
  31.         //  num 是[局部變量] 
  32.         breadNum = breadNum - num; 
  33.  
  34.         System.out.println(name + "吃了 " + num + " 個面包,全世界的面包還剩 " + breadNum + " 個!"); 
  35.     } 
  36.  
  37.     /** 
  38.      * [構(gòu)造方法] 
  39.      * 參數(shù)為空 
  40.      */ 
  41.     public Person() { 
  42.     } 
  43.  
  44.     /** 
  45.      * [構(gòu)造方法] 
  46.      * 
  47.      * @param name 此為構(gòu)造方法的輸入?yún)?shù),和成員變量有關(guān) 
  48.      */ 
  49.     public Person(String name) { 
  50.         this.name = name
  51.     } 
  52.  
  53.     /** 
  54.      * [靜態(tài)方法] 
  55.      */ 
  56.     static void testStaticMethod() { 
  57.  
  58.         // 通過構(gòu)造方法,初始化名字叫蝸牛的人 
  59.         Person woniu = new Person("蝸牛"); 
  60.  
  61.         // 通過構(gòu)造方法,初始化名字叫小白的人 
  62.         Person xiaobai = new Person("小白"); 
  63.  
  64.         // 假設全世界的面包數(shù)量就 100 個,并且生產(chǎn)已經(jīng)停滯 
  65.         Person.breadNum = 100; 
  66.  
  67.         // 蝸牛吃五個面包 
  68.         woniu.eatBread(5); 
  69.  
  70.         // 小白吃六個面包 
  71.         xiaobai.eatBread(6); 
  72.  
  73.         // 打印成員變量和靜態(tài)變量的值 
  74.         System.out.println(woniu.name + "和" + xiaobai.name + "吃飽后,世界只剩 " + Person.breadNum + " 個面包了!"); 
  75.  
  76.     } 

變量

首先定義了一個名字叫 Person 的類,表示人,然后定義了一個成員變量 name ,表示人的名字。成員變量也叫實例變量,實例變量的特點就是,每個實例都有獨立的變量,各個實例之間的同名變量互不影響。

其次定義了一個靜態(tài)變量 breadNum ,表示面包的數(shù)量,靜態(tài)變量用 static 修飾。靜態(tài)變量相對于成員變量就不一樣了,它是共享的,所有實例會共享這個變量。

方法

再接著定義了一個返回值為空,只有一個入?yún)⒌姆椒?eatBread(int num) ,方法入?yún)?num 作為局部變量參與了內(nèi)部的運算,通過和它的運算,靜態(tài)變量breadNum 的值得到了更新,并打印了一行操作信息。方法的語法結(jié)構(gòu)如下:

  1. 修飾符 返回類型 方法名(方法參數(shù)列表) { 
  2.     方法語句; 
  3.     return 方法返回值; 

另外定義了 Person 的構(gòu)造方法,你會發(fā)現(xiàn)構(gòu)造方法和實例方法的區(qū)別就在于它是沒有返回值的,因為它的目的很純粹,就是用來初始化對象實例的,和 new 搭配使用,所以它的方法名就是類名,它的入?yún)⒁捕己统蓡T變量有關(guān)。

到這里,你會發(fā)現(xiàn) Java 方法的返回值并不是那么重要,甚至沒有都可以!是的,Java 方法簽名只包括名稱和參數(shù)列表,它們是 JVM 標識方法的唯一索引,是不包含返回值的,更不包括各種修飾符或者異常類型。

請注意,任何 class 都是有構(gòu)造方法的,即便你代碼里不寫,Java 也會在編譯 class 文件的時候,默認生成一個無參構(gòu)造方法。但是只要你手動定義了構(gòu)造方法,編譯器就不會再生成。也就是說如果你僅定義了一個有參的構(gòu)造方法,那么編譯后的 class 是不會有無參構(gòu)造方法的。

最后就是靜態(tài)方法了,名字叫testStaticMethod ,方法內(nèi)部我們先用 new 的語法調(diào)用構(gòu)造方法,初始化了蝸牛和小白的Person 對象。這兩個對象就是 Person 這個類的實例,這兩個實例都有獨立空間,name 這個成員變量也只能在被實例化后使用,可以通過 對象.成員變量名 訪問。

接著我們通過 Person.breadNum 也就是 類名.靜態(tài)變量名 的方式,更新了面包數(shù)量這個值。你會發(fā)現(xiàn) breadNum 這個靜態(tài)變量無需實例化就能使用,因為就這個變量而言,Person 的每個實例都會共享同一個空間。這意味著,每個實例的修改,都會影響到這個變量值的變化。

然后我們通過調(diào)用方法 eatBread 并傳參的方式,影響到了面包數(shù)的值。

  1. package cn.java4u.oo; 
  2.  
  3. /** 
  4.  * @author 蝸牛 
  5.  * @from 公眾號:蝸牛互聯(lián)網(wǎng) 
  6.  */ 
  7. public class MainTest { 
  8.  
  9.     public static void main(String[] args) { 
  10.  
  11.  
  12.         // 靜態(tài)方法,通過 類名.靜態(tài)方法名 訪問 
  13.         Person.testStaticMethod(); 
  14.     } 

最后我們新定義一個觸發(fā)調(diào)用的入口函數(shù),通過 Person.testStaticMethod() 這樣 類名.靜態(tài)方法名 的方式就能訪問到靜態(tài)方法了。

抽象類與接口

抽象類顧名思義,就是會對同類事物做抽象,通常包括抽象方法、實例方法和成員變量。被抽象類和抽象類之間是 is-a 關(guān)系,這種關(guān)系要符合里氏替換原則,即抽象類的所有行為都適用于被抽象類,比如大象是一種動物,動物能做的事,大象都能做。代碼定義也很簡單,就是在 class 和抽象方法上加 abstract 修飾符。

  1. package cn.java4u.oo; 
  2.  
  3. /** 
  4.  * 抽象類 
  5.  * 
  6.  * @author 蝸牛 
  7.  * @from 公眾號:蝸牛互聯(lián)網(wǎng) 
  8.  */ 
  9. public abstract class AbstractClass { 
  10.  
  11.     String name
  12.  
  13.     /** 
  14.      * 實例方法 
  15.      * 
  16.      * @return name 
  17.      */ 
  18.     public String getName() { 
  19.         return name
  20.     } 
  21.  
  22.     /** 
  23.      * 抽象方法-操作 
  24.      * 
  25.      * @return 結(jié)果 
  26.      */ 
  27.     public abstract String operate(); 

如果一個抽象類只有一個抽象方法,那它就等于一個接口。接口是要求被普通類實現(xiàn)的,接口在被實現(xiàn)時體現(xiàn)的是 can-do 關(guān)系,它表達了對象具備的能力。鳥有飛的能力,宇宙飛船也有飛的能力,那么可以把飛的能力抽出來,有單獨的一個抽象方法。代碼定義也比較簡單,class 的關(guān)鍵字用 interface 來替換。

  1. package cn.java4u.oo; 
  2.  
  3. /** 
  4.  * 可飛翔 
  5.  * 
  6.  * @author 蝸牛 
  7.  * @from 公眾號:蝸牛互聯(lián)網(wǎng) 
  8.  */ 
  9. public interface Flyable { 
  10.  
  11.  
  12.     /** 
  13.      * 飛 
  14.      */ 
  15.     void fly(); 

內(nèi)部類

在 Java 源代碼文件中,只能定義一個類目與文件名完全一致的公開類。如果想在一個文件里定義另外一個類,在面向?qū)ο罄镆彩侵С值模蔷褪莾?nèi)部類。

內(nèi)部類分為以下四種:

  • 靜態(tài)內(nèi)部類:static class StaticInnerClass {}
  • 成員內(nèi)部類:private class InstanceInnerClass {}
  • 局部內(nèi)部類:class MethodClass {} ,定義在方法或者表達式內(nèi)部
  • 匿名內(nèi)部類:(new Thread() {}).start();

示例代碼如下:

  1. package cn.java4u.oo.innerclass; 
  2.  
  3. /** 
  4.  * 內(nèi)部類演示 
  5.  * 
  6.  * @author 蝸牛 
  7.  * @from 公眾號:蝸牛互聯(lián)網(wǎng) 
  8.  */ 
  9. public class InnerClassDemo { 
  10.  
  11.     /** 
  12.      * 成員內(nèi)部類 
  13.      */ 
  14.     private class InstanceInnerClass {} 
  15.  
  16.     /** 
  17.      * 靜態(tài)內(nèi)部類 
  18.      */ 
  19.     static class StaticInnerClass {} 
  20.  
  21.     public static void main(String[] args) { 
  22.  
  23.         // 兩個匿名內(nèi)部類 
  24.         (new Thread() {}).start(); 
  25.         (new Thread() {}).start(); 
  26.  
  27.         // 方法內(nèi)部類 
  28.         class MethodClass {} 
  29.  
  30.     } 

編譯后得到的 class 文件如下:

我們會發(fā)現(xiàn),無論什么類型的內(nèi)部類,都會編譯生成一個獨立的 .class 文件,只是內(nèi)部類文件的命名會通過 $ 連接在外部類后面,如果是匿名內(nèi)部類,會使用編號來標識。

類關(guān)系

關(guān)系是指事物之間有沒有單向或者相互作用或者影響的狀態(tài)。

類和類之間的關(guān)系分為 6 種:

  • 繼承:extends(is-a)
  • 實現(xiàn):implements(can-do)
  • 組合:類是成員變量(contains-a)
  • 聚合:類是成員變量(has-a)
  • 依賴:單向弱關(guān)系(使用類屬性,類方法、作為方法入?yún)ⅰ⒆鳛榉椒ǔ鰠?
  • 關(guān)聯(lián):互相平等的依賴關(guān)系(links-a)

序列化

內(nèi)存中的數(shù)據(jù)對象只有轉(zhuǎn)換為二進制流才可以進行數(shù)據(jù)持久化和網(wǎng)絡傳輸。

將數(shù)據(jù)對象轉(zhuǎn)換成二進制流的過程稱為對象的序列化(Serialization)。

將二進制流恢復為數(shù)據(jù)對象的過程稱為反序列化(Deserialization)。

常見的序列化使用場景是 RPC 框架的數(shù)據(jù)傳輸。

常見的序列化方式有三種:

  • Java 原生序列化。特點是兼容性好,不支持跨語言,性能一般。
  • Hessian 序列化。特點是支持跨語言,性能高效。
  • JSON 序列化。特點是可讀性好,但有安全風險。

封裝

封裝是在抽象基礎上決定信息是否公開,以及公開等級,核心問題是以什么樣的方式暴露哪些信息。

抽象是要找到成員和行為的共性,成員是行為的基本生產(chǎn)資料,具有一定的敏感性,不能直接對外暴露。封裝的主要任務是對成員、數(shù)據(jù)、部分內(nèi)部敏感行為實現(xiàn)隱藏。

對成員的訪問與修改必須通過定義公共的接口來進行,另外某些敏感方法或者外部不需要感知的復雜邏輯處理,一般也會進行封裝。

像智能音箱,與用戶交互的唯一接口就是語音輸入,封裝了內(nèi)部的實現(xiàn)細節(jié)和相關(guān)數(shù)據(jù)。

設計模式七大原則之一的迪米特法則也說明了封裝的要求,A 接口使用 B 接口,對 B 知道的要盡可能少。

包(package)這個名稱就很明顯體現(xiàn)了封裝的含義,它能起到把一個模塊封裝到一起,并由幾個接口開放給使用方。使用方只能看到接口信息,而看不到接口實現(xiàn)。另外包解決重名問題,相同類名在相同路徑下是不允許的,切換包路徑就可以起相同的類名。

訪問權(quán)限控制

我們編寫的程序要想讓使用方,能看到一些信息,又不能看到另外一些信息,這就涉及到信息隱藏了。

信息隱藏是面向?qū)ο蟪绦蛟O計的重要特點之一,它可以防止類的使用者意外損壞數(shù)據(jù),對任何實現(xiàn)細節(jié)所作的修改不會影響到使用該類的其它代碼,也使類更易于使用。

那在 Java 里,實現(xiàn)信息隱藏的就是訪問權(quán)限控制機制了。Java 的訪問權(quán)限控制有 4 個訪問修飾符:public 、protected 、private 和缺省。可以使用這四個訪問修飾符修飾類的成員,它們在不同位置的可訪問性如下表所示。

位置\訪問修飾符 public protected 缺省 private
本類 可以 可以 可以 可以
本包 可以 可以 可以 不可以
子類 可以 可以 不可以 不可以
所有 可以 不可以 不可以 不可以

你會發(fā)現(xiàn) public 不受任何限制,本類和非本類都可以隨意訪問(全局友好)。protected 本類及其子類可以訪問(父子友好),同一個包中的其它類也可以訪問(包內(nèi)友好)。而缺省的時候,只有相同包中的類可以訪問(包內(nèi)友好)。private 只有本類可以訪問,其余都不可以(類內(nèi)友好)。

除了為類成員添加訪問權(quán)限控制外,也可以在定義類的時候,為類添加訪問修飾符,對類進行訪問權(quán)限控制。不過對類使用的訪問修飾符只有 public 和缺省兩種,訪問范圍也分別是全局友好和包內(nèi)友好。

getter 與 setter

為了讓類成員不對外直接暴露,我們經(jīng)常把成員變量的訪問權(quán)限設置成 private,而成員值的訪問與修改使用相應的 getter/setter 方法。而不是對 public 的成員進行讀取和修改。

  1. package cn.java4u.oo.packagedemo; 
  2.  
  3. /** 
  4.  * getter 和 setter 演示 
  5.  * @author 蝸牛 
  6.  * @from 公眾號:蝸牛互聯(lián)網(wǎng) 
  7.  */ 
  8. public class GetterSetterDemo { 
  9.  
  10.     /** 
  11.      * 成員變量私有化 
  12.      */ 
  13.     private String name
  14.  
  15.     /** 
  16.      * 公開方法獲取成員變量值 
  17.      * 
  18.      * @return 名稱 
  19.      */ 
  20.     public String getName() { 
  21.         return name
  22.     } 
  23.  
  24.     /** 
  25.      * 公開方法設置成員變量值 
  26.      * 
  27.      * @param name 名稱 
  28.      */ 
  29.     public void setName(String name) { 
  30.         this.name = name
  31.     } 

繼承

類繼承

class 了解之后,我們考慮一個問題。如果兩個 class,它們的變量和方法基本相同,僅僅是其中一個 class 會有一些自己特有的變量和方法,那么相同的那些變量和方法真的需要在兩個 class 里都寫一遍么?

比如一個表示學生的 class Student ,它相對于 class Person 只是多了一個分數(shù) score 的成員變量,那還需要像下面這樣,把 name 字段也定義一下么?

  1. /** 
  2.  * 學生 
  3.  * 
  4.  * @author 蝸牛 
  5.  * @from 公眾號:蝸牛互聯(lián)網(wǎng) 
  6.  */ 
  7. public class Student { 
  8.  
  9.     /** 
  10.      * 名字 
  11.      */ 
  12.     String name
  13.  
  14.     /** 
  15.      * 分數(shù) 
  16.      */ 
  17.     int score; 
  18.  

這很明顯帶來了代碼重復使用的問題!那能不能在 Student 中不寫重復代碼?

Java 里的繼承這時候就派上用場了,繼承是面向?qū)ο缶幊痰囊环N強大機制,能夠讓子類繼承父類的特征和行為,使得子類對象能夠具有父類的實例變量和方法。

子類繼承父類,父類派生子類。父類也叫基類,子類也叫派生類。

通常來講,類的層次劃分總是下一層比上一層更具體,并且包含上一層的特征,這樣下層的類就能自動享有上層類的特點和性質(zhì)。繼承就是派生類自動地共享基類中成員變量和成員方法的機制。

在 Java 中,通過 extends 關(guān)鍵字實現(xiàn)繼承,并且所有的類都是繼承于 java.lang.Object ,所以這就是萬物皆對象在 Java 里的真實寫照。你可能會疑惑,自定義的類并沒有 extends 關(guān)鍵字為什么還能繼承 Object 呢?這是因為這個類在 java.lang 包里,Java 已經(jīng)默認支持了。

  1. package cn.java4u.oo; 
  2.  
  3. /** 
  4.  * 學生 
  5.  * 
  6.  * @author 蝸牛 
  7.  * @from 公眾號:蝸牛互聯(lián)網(wǎng) 
  8.  */ 
  9. public class Student extends Person { 
  10.  
  11.     /** 
  12.      * 分數(shù) 
  13.      */ 
  14.     int score; 
  15.  

知道了繼承的基礎概念后,我們看下繼承有啥作用?

首先,繼承是能夠自動傳播代碼和重用代碼的有力工具。它能在已有類上擴充新類,減少代碼的重復冗余,也因為冗余度降低,一致性就得到了增強,從而提升了程序的可維護性。

其次,繼承可以清晰體現(xiàn)出類與類之間的層次結(jié)構(gòu)關(guān)系,提升了代碼的可讀性。

另外,繼承是單方向的,即派生類可以繼承和訪問基類成員,但反過來就不行。而且 Java 只允許單一繼承,也就是一個派生類不能同時繼承多個基類,這和 C++ 是不同的。

在使用繼承的時候,還要考慮到基類成員的訪問控制權(quán)限。可以參考封裝那塊內(nèi)容的訪問權(quán)限控制介紹。

子類實例化過程

特別要說明的是,父類的構(gòu)造方法是不能被子類繼承的,即便它是 public 的。父類的構(gòu)造方法負責初始化屬于它的成員變量,而子類的構(gòu)造方法只需考慮自己特有的成員變量即可,不必關(guān)注父類狀況。

  1. package cn.java4u.oo.inherit; 
  2.  
  3. /** 
  4.  * 定義父類 
  5.  * 
  6.  * @author 蝸牛 
  7.  * @from 公眾號:蝸牛互聯(lián)網(wǎng) 
  8.  */ 
  9. public class Parent { 
  10.  
  11.  
  12.     /** 
  13.      * 構(gòu)造方法 
  14.      */ 
  15.     public Parent() { 
  16.  
  17.         System.out.println("這是父類 Parent 的構(gòu)造方法"); 
  18.     } 
  19.  
  20. package cn.java4u.oo.inherit; 
  21.  
  22. /** 
  23.  * 定義子類 
  24.  * 
  25.  * @author 蝸牛 
  26.  * @from 公眾號:蝸牛互聯(lián)網(wǎng) 
  27.  */ 
  28. public class Child extends Parent { 
  29.  
  30.     /** 
  31.      * 構(gòu)造方法 
  32.      */ 
  33.     public Child() { 
  34.  
  35.         System.out.println("這是子類 Child 的構(gòu)造方法"); 
  36.  
  37.     } 
  38.  
  39. package cn.java4u.test; 
  40.  
  41. import cn.java4u.oo.inherit.Child; 
  42.  
  43. /** 
  44.  * @author 蝸牛 
  45.  * @from 公眾號:蝸牛互聯(lián)網(wǎng) 
  46.  */ 
  47. public class InheritTest { 
  48.  
  49.     public static void main(String[] args) { 
  50.  
  51.         Child child = new Child(); 
  52.     } 

因此,在實例化子類的對象時,Java 先是執(zhí)行父類的構(gòu)造方法,然后執(zhí)行子類的構(gòu)造方法。如果父類還有更上級的父類,就會先調(diào)用更高父類的構(gòu)造方法,再逐個依次地將所有繼承關(guān)系的父類構(gòu)造方法全部執(zhí)行。如果父類的構(gòu)造方法執(zhí)行失敗,則子類的對象也將無法實例化。

上邊的代碼運行后,會輸出:

  1. 這是父類 Parent 的構(gòu)造方法 
  2. 這是子類 Child 的構(gòu)造方法 

this 與 super

如果調(diào)用父類構(gòu)造方法涉及到有參構(gòu)造方法,可以使用 super 關(guān)鍵字來調(diào)用父類構(gòu)造方法并傳遞參數(shù)。

說的 super,它還有一個能力,就是父類和子類的成員如果同名了,子類中默認只能訪問自己的那個成員,想要訪問父類成員,就可以通過 super.成員名 的語法實現(xiàn)。但這有個前提,就是父類的這個成員不能是 private 的。

與 super 相對的關(guān)鍵字是 this ,super 是指向當前對象的父類,而 this 是指向當前對象自己。this 常用來區(qū)別成員變量和局部變量,比如下面這段代碼,我加了個有參構(gòu)造方法。

  1. public class Parent { 
  2.  
  3.     int a; 
  4.  
  5.     /** 
  6.      * 構(gòu)造方法 
  7.      */ 
  8.     public Parent() { 
  9.  
  10.         System.out.println("這是父類 Parent 的構(gòu)造方法"); 
  11.     } 
  12.  
  13.     public Parent(int a) { 
  14.         this.a = a; 
  15.     } 
  16.  
  17.  

多態(tài)

說完繼承,我們再來聊聊多態(tài)!

多態(tài)字面上解釋,就是程序可以有多個運行狀態(tài)。

既然是運行狀態(tài),那其實更多的是強調(diào)方法的使用。

重載與覆寫

方法在兩種情況下使用會比較特別,一種是 overload(重載),overload 方法是本類內(nèi)的新方法,方法名一樣,但是參數(shù)的類型或數(shù)量不同。這種方法沒有特殊的標識,通過類內(nèi)方法是否重名判定。

另外一種就是 override(覆寫),override 方法是繼承關(guān)系下子類的新方法,方法簽名和父類完全相同。這種方法都會有 @Override 注解的標識。

  1. package cn.java4u.oo.polymorphism; 
  2.  
  3. /** 
  4.  * 動物 
  5.  * 
  6.  * @author 蝸牛 
  7.  * @from 公眾號:蝸牛互聯(lián)網(wǎng) 
  8.  */ 
  9. public class Animal { 
  10.  
  11.  
  12.     /** 
  13.      * 與 eat(String food) 重載 
  14.      */ 
  15.     public void eat() { 
  16.         System.out.println("Animal.eat"); 
  17.     } 
  18.  
  19.     /** 
  20.      * 與 eat() 重載 
  21.      * 
  22.      * @param food 食物 
  23.      */ 
  24.     public void eat(String food) { 
  25.         System.out.println("Animal.eat: " + food); 
  26.     } 
  27.  
  28.     /** 
  29.      * 覆寫 
  30.      * 
  31.      * @return 字符串 
  32.      * @see java.lang.Object#toString 
  33.      */ 
  34.     @Override 
  35.     public String toString() { 
  36.         return "Animal " + super.toString(); 
  37.     } 

舉個例子,Animal 類里兩個 eat 方法就互為重載方法,toString 方法就是相對于父類方法 java.lang.Object#toString 的覆寫方法。

多態(tài)就發(fā)生在覆寫這種場景下。針對某個類型的方法調(diào)用,它真正執(zhí)行的方法取決于運行時期實際類型的方法。比如下面這段代碼,當聲明類型為 Object ,初始化類型為 Animal 時,你覺得輸出的是 Animal 的 toString 方法,還是 Object 的 toString 方法?

  1. package cn.java4u.oo.polymorphism; 
  2.  
  3. /** 
  4.  * @author 蝸牛 
  5.  * @from 公眾號:蝸牛互聯(lián)網(wǎng) 
  6.  */ 
  7. public class PolymorphismTest { 
  8.  
  9.     /** 
  10.      * 打印對象 
  11.      * 
  12.      * @param scene 打印場景 
  13.      * @param obj   obj 
  14.      */ 
  15.     public static void printObjectString(String scene, Object obj) { 
  16.  
  17.         System.out.println(scene + ": " + obj.toString()); 
  18.  
  19.     } 
  20.  
  21.     public static void main(String[] args) { 
  22.  
  23.         // 父類引用初始化父類對象并打印 
  24.         Object rootObj = new Object(); 
  25.         printObjectString("父類引用初始化父類對象", rootObj); 
  26.  
  27.         // 子類引用初始化子類對象并打印 
  28.         Animal animal = new Animal(); 
  29.         printObjectString("子類引用初始化子類對象", animal); 
  30.  
  31.  
  32.         // 父類引用初始化子類對象并打印 
  33.         Object animalWhenParentRef = new Animal(); 
  34.         printObjectString("父類引用初始化子類對象", animal); 
  35.          
  36.     } 

答案是子類 Animal 的 toString 方法!

  1. 父類引用初始化父類對象: java.lang.Object@60e53b93 
  2. 子類引用初始化子類對象: Animal cn.java4u.oo.polymorphism.Animal@5e2de80c 
  3. 父類引用初始化子類對象: Animal cn.java4u.oo.polymorphism.Animal@5e2de80c 

實際類型為 Animal 引用類型為 Object ,調(diào)用 toString 方法時,實際上是子類的。因此我們可以得出結(jié)論:Java 的實例方法調(diào)用是基于運行時的實際類型的動態(tài)調(diào)用,而非變量的聲明類型。這種特性就是多態(tài)!

你會發(fā)現(xiàn) printObjectString 方法的第二個參數(shù),即便聲明的是 Object ,實際運行的時候,卻可以是它的子類覆寫方法。

至此,我們也理出了 Java 實現(xiàn)多態(tài)三要素,那就是 繼承、覆寫和向上轉(zhuǎn)型。即兩個類之間有繼承關(guān)系,某個類覆寫了父類的某個方法,方法的引用會指向子類的實現(xiàn)處。

總結(jié)

本文從 Java 的視角出發(fā),分析了 Java 的語言特點,并和 C++ 進行了比較。針對這門典型的面向?qū)ο笳Z言,我們又分析了面向?qū)ο蟮母拍詈退枷搿=又诿嫦驅(qū)ο蟮奶卣鳎撼橄蟆⒎庋b、繼承和多態(tài),我們又詳細的分析了在 Java 中的體現(xiàn)方式,并伴有很多樣例代碼輔助學習。看完這篇文章,想必你對面向?qū)ο筮@個東西會有更全面的了解。

好啦,本期的分享就到這里,如果各位喜歡我的分享,請務必三連,點贊,在看,收藏,關(guān)注我,這會對我有非常大的幫助。

 

我們下期再見。

 

責任編輯:武曉燕 來源: 蝸牛互聯(lián)網(wǎng)
相關(guān)推薦

2009-07-09 17:40:26

Java運算符

2023-11-08 07:45:47

Spring微服務

2010-11-15 09:55:35

Oracle轉(zhuǎn)換函數(shù)

2019-04-26 14:21:34

手機色彩蘋果

2011-01-11 09:53:28

linux進程

2011-01-11 10:06:14

linux進程

2017-03-06 16:34:12

虛擬個人助理

2010-10-14 16:55:00

MySQL聯(lián)結(jié)查詢

2009-03-03 20:44:06

桌面虛擬化Xendesktop虛擬化

2020-02-17 15:29:00

石墨文檔

2014-08-11 11:19:53

Java虛擬機Java

2009-06-22 17:20:33

J2EE框架

2013-10-18 14:23:21

Ubuntu 13.1Kbuntu 13.1

2010-09-14 13:13:12

sql server備

2011-05-26 10:27:37

Fedora 15

2009-09-28 10:58:31

Google新搜索特性

2024-02-05 14:18:07

自然語言處理

2012-02-20 09:06:20

JVM

2017-04-25 17:29:24

2017-09-06 08:12:43

OpenStack功能模塊
點贊
收藏

51CTO技術(shù)棧公眾號

91麻豆视频网站| 中文字幕一区二区三区在线视频| 精品久久久久久久久久久久久久 | 久久免费公开视频| av自拍一区| 色老汉av一区二区三区| 在线丝袜欧美日韩制服| 风流老熟女一区二区三区| 国产亚洲高清视频| 色偷偷av一区二区三区乱| 国模大尺度视频| 三级在线看中文字幕完整版| 国产精品成人免费精品自在线观看 | 久久精品国产亚洲高清剧情介绍 | 日韩电影免费看| 中文字幕一区三区| 裸体丰满少妇做受久久99精品| 中文字幕精品一区二| 欧美日韩国产欧| 国产亚洲精品久久久久久777| 91香蕉国产线在线观看| 樱桃视频成人在线观看| 亚洲免费在线视频| 亚洲国产一区二区三区在线| 男人天堂网在线视频| 另类小说综合欧美亚洲| 欧美中文在线观看| 欧美精品一级片| 国产一区99| 亚洲国产天堂久久综合| 美女黄色片视频| 激情国产在线| 夜夜精品浪潮av一区二区三区| 三区精品视频观看| 水莓100在线视频| 福利电影一区二区| 91香蕉嫩草影院入口| 日本中文字幕在线观看视频| 亚洲黄页一区| 欧美理论电影在线观看| 在线日韩国产网站| 欧美一区二区三区激情视频 | 精品无码一区二区三区| 国产不卡精品| 欧美蜜桃一区二区三区| 日韩精品你懂的| 国模一区二区| 色婷婷综合五月| 日日碰狠狠添天天爽超碰97| 国产偷倩在线播放| 一区二区三区欧美久久| 中文字幕免费高| 超碰在线观看免费| 亚洲欧洲另类国产综合| 亚洲精品国产精品国自产观看| 欧美美乳在线| 久久久www免费人成精品| 久久国产精品一区二区三区四区| 蜜桃av鲁一鲁一鲁一鲁俄罗斯的 | 波多野结衣一二三四区| 国产剧情在线观看一区| 亚洲色图欧美制服丝袜另类第一页| 三级视频网站在线观看| 日韩高清影视在线观看| 精品一区二区电影| www.狠狠爱| jiujiure精品视频播放| 中文字幕精品在线视频| 在线观看天堂av| 一本一本久久a久久综合精品| 欧美成人免费大片| 精品一区在线视频| 亚洲经典在线看| 热门国产精品亚洲第一区在线| 亚洲免费黄色网址| 免费在线一区观看| 成人有码视频在线播放| 亚洲av永久纯肉无码精品动漫| 成人综合激情网| 美国av一区二区三区| 精品美女视频在线观看免费软件| 欧美国产综合一区二区| 中文字幕黄色大片| 成人超碰在线| 色欧美片视频在线观看| 伊人网在线综合| 8848成人影院| 亚洲欧美日韩在线一区| 正在播放国产对白害羞| 欧美日韩网站| 秋霞成人午夜鲁丝一区二区三区| 伊人色综合久久久| 国产精品白丝jk白祙喷水网站| 国产精品果冻传媒潘| 毛片免费在线观看| 亚洲日本在线视频观看| 欧美 丝袜 自拍 制服 另类| 成人性片免费| 亚洲第一网中文字幕| 精品人妻中文无码av在线| 911精品美国片911久久久| 97碰碰碰免费色视频| 这里只有精品999| 国产成人av电影在线播放| 欧美一区1区三区3区公司 | 欧美性猛交xxxx偷拍洗澡| 污版视频在线观看| 欧美成人一区在线观看| 色偷偷噜噜噜亚洲男人| 日本在线免费观看| 激情五月激情综合网| 久久久久久久久久久一区 | 亚洲男人天堂一区| 亚洲精品中文字幕无码蜜桃| 日韩精品一区二区三区中文在线 | 国产1区在线| 一本在线高清不卡dvd| 日批视频在线看| 日韩精品dvd| 91高清免费在线观看| 99久久精品无免国产免费| 久久夜色精品一区| 欧美国产日韩激情| 久久久国产精品入口麻豆| 国产一区二区精品丝袜| 国产欧美日韩另类| 国产福利一区二区三区视频在线| 色噜噜狠狠一区二区三区| 伊人久久精品一区二区三区| 精品精品国产高清a毛片牛牛| 欧美另类69xxxx| 天堂精品中文字幕在线| 国产精品一区二区三区观看| 成人影院www在线观看| 欧美性受极品xxxx喷水| 亚洲精品成人无码熟妇在线| 亚洲激情综合| 国产日韩三区| 成人av影院在线观看| 欧美xfplay| 欧美成人手机视频| 国产精品主播直播| 成人在线观看www| 成人动漫视频在线观看| 日韩最新在线视频| 亚洲一级av毛片| 国产精品每日更新在线播放网址| 天天天干夜夜夜操| 狠狠做六月爱婷婷综合aⅴ| 国产aⅴ夜夜欢一区二区三区| av女名字大全列表| 精品高清一区二区三区| 污污内射在线观看一区二区少妇| 国产一区日韩欧美| 国产视色精品亚洲一区二区| 国产www视频在线观看| 日韩欧美成人一区| 久久精品美女视频| 97se亚洲国产综合自在线不卡| 亚洲 自拍 另类小说综合图区| av成人综合| 97色伦亚洲国产| 深夜视频在线免费| 色狠狠色狠狠综合| 女教师淫辱の教室蜜臀av软件| 久久福利视频一区二区| 国产精品久久成人免费观看| 欧一区二区三区| 97免费在线视频| 国产三级在线免费| 欧美另类久久久品| 九九精品视频免费| 国产.欧美.日韩| 国产淫片免费看| 国产成人影院| 国产有码一区二区| 日韩123区| 亚洲免费视频网站| 91高潮大合集爽到抽搐| 亚洲精品成a人| 在线观看国产免费视频| 日韩国产欧美视频| 大桥未久一区二区三区| 日本午夜精品| 国产精品视频网址| 国产深夜视频在线观看| 亚洲免费一级电影| 999久久久久久| 亚洲国产裸拍裸体视频在线观看乱了| 欧美成人三级伦在线观看| 日韩黄色片在线观看| 欧美少妇在线观看| 日韩欧美中文字幕电影| 91精品久久久久久久久久另类| 欧美精品videosex| 亚洲一二在线观看| 亚洲黄色在线免费观看| 色婷婷综合久久久| 欧美激情图片小说| 久久久久久久久久久黄色| 日韩av自拍偷拍| 国产日本精品| ijzzijzzij亚洲大全| 亚洲免费观看高清完整版在线观| 成人黄色午夜影院| 小早川怜子影音先锋在线观看| 精品国内产的精品视频在线观看| 婷婷综合激情网| 欧美三级乱人伦电影| 久草精品视频在线观看| 国产精品成人网| 欧美偷拍一区二区三区| 成人av在线电影| 午夜天堂在线视频| 视频在线在亚洲| 肉大捧一出免费观看网站在线播放| 国产91精品对白在线播放| 91成人免费视频| 国产精品伊人| 日本久久久久久| xxxx视频在线| 久久成人精品一区二区三区| 九色国产在线观看| 亚洲国产小视频| 午夜精品久久久久久久96蜜桃 | 亚洲国产www| 欧美日韩一级片网站| 欧美亚洲精品天堂| 亚洲国产日韩一级| 麻豆精品一区二区三区视频| 中文字幕精品在线不卡| 草草影院第一页| 久久午夜老司机| 欧美精品欧美极品欧美激情| 国产成人在线视频网址| 加勒比av中文字幕| 麻豆高清免费国产一区| 国语对白做受xxxxx在线中国| 好看的亚洲午夜视频在线| 黄黄视频在线观看| 欧美一区亚洲| 91网站在线观看免费| 欧美日本不卡| 老司机激情视频| 亚洲福利免费| 国产日韩欧美精品在线观看| 亚洲午夜一区| 亚洲国产精品无码观看久久| 国产一区二区三区四区三区四| 高清无码一区二区在线观看吞精| 欧美成人午夜| 日本五级黄色片| 亚洲成人中文| 777久久久精品一区二区三区| 国产一区二区你懂的| 国产综合中文字幕| 亚洲欧美日韩国产一区二区| 国产精品-区区久久久狼| 亚洲免费中文| 日韩视频免费在线播放| 男女视频一区二区| 精品国产乱码久久久久久1区二区| 激情久久五月天| 日本中文字幕精品| 成人福利在线看| 全黄一级裸体片| 国产精品久久久久久久久免费丝袜| 国产一区二区三区视频播放| 亚洲男人的天堂一区二区| 免费在线观看日韩| 精品国产户外野外| 波多野结衣在线观看视频| 欧美色图片你懂的| 99久久99久久久精品棕色圆| 欧美xxxxxxxx| 欧洲天堂在线观看| 日韩一区二区av| 男女在线视频| 国产不卡视频在线| 国产精品一区三区在线观看| 国产日韩精品推荐| 大色综合视频网站在线播放| 国产内射老熟女aaaa| 久久福利精品| 在线播放免费视频| 91啪九色porn原创视频在线观看| 国产91丝袜美女在线播放| 亚洲精品日日夜夜| 成人公开免费视频| 91精品在线麻豆| 蜜桃成人在线视频| 麻豆国产精品va在线观看不卡| 高端美女服务在线视频播放| 国产精品日韩欧美大师| 国产精品115| 一区二区三区我不卡| 亚洲欧洲一区| 日韩 国产 一区| 久久久亚洲精品一区二区三区| 乱h高h女3p含苞待放| 色欧美乱欧美15图片| 蜜臀av免费在线观看| 日韩中文字幕在线免费观看| 欧亚在线中文字幕免费| 亚洲aⅴ男人的天堂在线观看 | 色综合.com| 国产在线欧美日韩| 99久久亚洲精品蜜臀| 日韩欧美精品在线观看视频| 国产福利一区在线| 在线日韩国产网站| 91福利国产成人精品照片| 好吊视频一二三区| www.xxxx欧美| 亚洲欧洲日本韩国| 97av影视网在线观看| 国产99久久| 福利视频一二区| 激情深爱一区二区| 美女网站视频色| 色综合久久久久久久| 中文字幕精品视频在线观看| 欧美岛国在线观看| 亚乱亚乱亚洲乱妇| 国产精品va在线播放| 欧美a大片欧美片| 日本a在线免费观看| 韩国视频一区二区| 亚洲AV无码国产成人久久| 激情懂色av一区av二区av| 国产绳艺sm调教室论坛| 色先锋资源久久综合5566| 校园春色亚洲| 国产精品12| 国语精品一区| 久久出品必属精品| 亚洲欧美视频一区| 亚洲一区二区色| 亚洲一区二区久久久| 欧美色网在线| 蜜桃在线一区二区三区精品| 国产免费成人| av无码一区二区三区| 亚洲午夜在线视频| 成人毛片在线免费观看| 美女精品视频一区| 成人在线视频中文字幕| 蜜桃视频一区二区在线观看| 国产精品亚洲产品| 欧美亚一区二区三区| 午夜欧美2019年伦理| 亚洲欧洲成人在线| 91精品国产一区| 草莓视频一区二区三区| 国精产品一区一区三区视频| 成人在线综合网站| 国产又爽又黄的视频| 日韩成人中文字幕| 精品3atv在线视频| 日韩av电影免费播放| 日韩高清在线不卡| 永久免费看片直接| 欧美精品乱人伦久久久久久| av免费在线观看网址| **亚洲第一综合导航网站| 天天综合亚洲| 人妻av一区二区三区| 亚洲一二三区在线观看| 天天av综合网| 国产精品99蜜臀久久不卡二区| 日韩在线中文| 欧美在线a视频| 亚洲风情在线资源站| 九色视频在线观看免费播放| 国产成人精品久久二区二区| 欧美wwwww| 1314成人网| 一本到一区二区三区| 成人精品一区二区三区免费| 国产欧美日韩高清| 国产在线不卡| 在线免费观看黄色小视频| 欧美日韩aaaaa| 性欧美ⅴideo另类hd| 久久久久网址| 久久精品国产免费| 人人妻人人澡人人爽| 日韩欧美国产一区在线观看| 久久av色综合| 色播亚洲视频在线观看| 国内精品伊人久久久久av一坑| 国产一级在线观看视频| 亚洲欧洲美洲在线综合| 日韩成人18| 国产成人a亚洲精v品无码| 日本一区二区视频在线| 超碰在线观看99| 国产成人精品999| 尤物精品在线| 黑人と日本人の交わりビデオ|