摘要:自從轉(zhuǎn)到前段,差不多有一年時(shí)間沒有動(dòng)了,今天老弟問我關(guān)于的面向?qū)ο?,自己不敢直接回答了,也許自己真的應(yīng)該去做相關(guān)的考究了。要有父類引用指向子類對(duì)象。外部類要訪問內(nèi)部類的成員,必須要建立內(nèi)部類的對(duì)象。
自從轉(zhuǎn)到前段,差不多有一年時(shí)間沒有動(dòng)Java了,今天老弟問我關(guān)于Java的面向?qū)ο?,自己不敢直接回答了,也許自己真的應(yīng)該去做相關(guān)的考究了。然后在告訴他吧,記在這里當(dāng)做一個(gè)筆記吧。
什么是繼承就是把多個(gè)具有具有相同的屬性和行為的類抽象到一個(gè)類,然后遇到相似的行為和屬性,就可以直接繼承,沒有重復(fù)寫。
優(yōu)點(diǎn)復(fù)用性強(qiáng)
類與類之間有關(guān)系,是多態(tài)的前提
繼承的特點(diǎn)1, Java只支持單繼承
//一個(gè)類只能有一個(gè)父類,不可以有多個(gè)父類。 class SubDemo extends Demo{} //ok class SubDemo extends Demo1,Demo2...//error
2, Java支持多層(重)繼承(繼承體系)
class A{} class B extends A{} class C extends B{}super和this有什么區(qū)別
super是一個(gè)關(guān)鍵字,代表父類的存儲(chǔ)空間標(biāo)識(shí)。(可以理解為父親的引用)
super和this的用法相似。
this代表對(duì)象的引用(誰調(diào)用就代表誰);
super代表當(dāng)前子類對(duì)父類的引用。
使用場景
當(dāng)子父類出現(xiàn)同名成員時(shí),可以用super進(jìn)行區(qū)分;
子類要調(diào)用父類構(gòu)造函數(shù)時(shí),可以使用super語句。
區(qū)別1 成員變量
this.變量 -- 本類的 super.變量 -- 父類的
2.構(gòu)造方法
this(...) -- 本類的 super(...) -- 父類的
3.成員方法
this.方法名() -- 本類的 super.方法名() -- 父類的 super();和this();都是在構(gòu)造函數(shù)的第一行,不能同時(shí)出現(xiàn)。方法的重寫(覆蓋)
子類中出現(xiàn)與父類一模一樣的方法時(shí)(除了權(quán)限修飾符,權(quán)限修飾符大于等于不包括private,返回值類型,方法名和參數(shù)列表相同),會(huì)出現(xiàn)覆蓋操作,也稱為重寫或者復(fù)寫。
父類私有方法,子類看不到,因此父類私有方法的重寫也就無從談起。
多態(tài)多態(tài)的前提:
要有繼承或者實(shí)現(xiàn)關(guān)系。
要有方法的重寫。
要有父類引用指向子類對(duì)象。
多態(tài)自始至終都是子類對(duì)象在變化!
//多態(tài)向下轉(zhuǎn)型和向上轉(zhuǎn)型的例子, //多態(tài)轉(zhuǎn)型解決了多態(tài)中父類引用不能使用子類特有成員的弊端。 class PolymorphicTest2 { public static void main(String[] args) { Phone p1 = new Nokia(); //向上轉(zhuǎn)型,類型提升 Nokia no = (Nokia)p1; //向下轉(zhuǎn)型,強(qiáng)制將父類的引用轉(zhuǎn)換成子類類型,不能將Nokia類型轉(zhuǎn)成 Moto或Nexus類型 no.print(); //輸出結(jié)果為Phone---null---0,因?yàn)槔^承了父類的方法 Phone p2 = new Moto(); Moto m = (Moto)p2; m.print(); //輸出結(jié)果為Moto---yellow---1599,方法重寫,子類方法覆蓋父類方法 Phone p3 = new Nexus(); Nexus ne = (Nexus)p3; ne.print(); } } class Phone{ String color; int price; public void print(){ System.out.println("Phone---" + color + "---" + price ); } } class Nokia extends Phone{ String color = "red"; int price = 1009; //public void print(){ // System.out.println("Nokia---" + color + "---" + price); //} } class Moto extends Phone{ String color = "yellow"; int price = 1599; public void print(){ System.out.println("Moto---" + color + "---" + price); } } class Nexus extends Phone{ String color = "black"; int price = 1999; public void print(){ System.out.println("Nexus---" + color + "---" + price); } } }抽象(abstract)
抽象就是從多個(gè)事物中將共性的,本質(zhì)的內(nèi)容抽象出來。
抽象類:Java中可以定義沒有方法體的方法,該方法的具體實(shí)現(xiàn)由子類完成,該方法稱為抽象方法,包含抽象方法的類就是抽象類。
由來:多個(gè)對(duì)象都具備相同的功能,但是功能具體內(nèi)容有所不同,那么在抽取過程中,只抽取了功能定義,并未抽取功能主體,那么只有功能聲明,沒有功能主體的方法稱為抽象方法。
抽象類特點(diǎn):抽象方法一定在抽象類中;
抽象方法和抽象類都必須被abstract關(guān)鍵字修飾;
抽象類不可以用new創(chuàng)建對(duì)象,因?yàn)檎{(diào)用抽象方法沒意義;
抽象類中的抽象方法要被使用,必須由子類復(fù)寫其所有的抽象方法后,建立子類對(duì)象調(diào)用; 如果子類只覆蓋了部分* 的抽象方法,那么該子類還是一個(gè)抽象類;
抽象類中可以有抽象方法,也可以有非抽象方法,抽象方法用于子類實(shí)例化;
如果一個(gè)類是抽象類,那么,繼承它的子類,要么是抽象類,要么重寫所有抽象方法。
特殊:抽象類中可以不定義抽象方法,這樣做僅僅是不讓該類建立對(duì)象。
抽象類的成員特點(diǎn):1, 成員變量:可以是變量,也可以是常量;
2, 構(gòu)造方法:有構(gòu)造方法;
3, 成員方法:可以是抽象方法,也可以是非抽象方法。
abstract class 葵花寶典 { public abstract void 自宮(); } class 岳不群 extends 葵花寶典 { public void 自宮(){ System.out.println("剪刀"); } } class 林平之 extends 葵花寶典{ public void 自宮(){ System.out.println("指甲刀"); } } class AbstractTest { public static void main(String[] args) { 岳不群 岳 = new 岳不群(); 岳.自宮(); 林平之 林 = new 林平之(); 林.自宮(); } }抽象類注意事項(xiàng):
抽象類不能被實(shí)例化,為什么還有構(gòu)造函數(shù)?
只要是class定義的類里面就肯定有構(gòu)造函數(shù)。抽象類中的函數(shù)是給子類實(shí)例化的。
一個(gè)類沒有抽象方法,為什么定義為抽象類?
不想被繼承,還不想被實(shí)例化。
抽象關(guān)鍵字abstract不可以和哪些關(guān)鍵字共存?
final:如果方法被抽象,就需要被覆蓋,而final是不可以被覆蓋,所以沖突。
private:如果函數(shù)被私有了,子類無法直接訪問,怎么覆蓋呢?
static:不需要對(duì)象,類名就可以調(diào)用抽象方法。而調(diào)用抽象方法沒有意義。
接口是抽象方法和常量值的集合。從本質(zhì)上講,接口是一種特殊的抽象類,這種抽象類只包含常量和方法的定義,而沒有變量和方法的實(shí)現(xiàn)。
格式:interface 接口名{}
接口的出現(xiàn)將"多繼承"通過另一種形式體現(xiàn)出來,即"多實(shí)現(xiàn)"。
實(shí)現(xiàn)(implements)格式:class 類名 implements 接口名 {}
特點(diǎn):
接口不能被實(shí)例化。
一個(gè)類如果實(shí)現(xiàn)了接口,要么是抽象類,要么實(shí)現(xiàn)接口中的所有方法。
接口的成員特點(diǎn):
接口中的成員修飾符是固定的!
成員常量:public static final,接口里定義的變量是全局常量,而且修飾符只能是這三個(gè)關(guān)鍵字,都可以省略,常量名要大寫。
成員方法:public abstract,接口里定義的方法都是抽象的,兩個(gè)修飾符關(guān)鍵字可省略。
推薦:永遠(yuǎn)手動(dòng)給出修飾符。
繼承與實(shí)現(xiàn)的區(qū)別:
類與類之間稱為繼承關(guān)系:因?yàn)樵擃悷o論是抽象的還是非抽象的,它的內(nèi)部都可以定義非抽象方法,這個(gè)方法可以直接被子類使用,子類繼承即可。只能單繼承,可以多層繼承。((class))
類與接口之間是實(shí)現(xiàn)關(guān)系:因?yàn)榻涌谥械姆椒ǘ际浅橄蟮?,必須由子類?shí)現(xiàn)才可以實(shí)例化。可以單實(shí)現(xiàn),也可以多實(shí)現(xiàn);還可以在繼承一個(gè)類的同時(shí)實(shí)現(xiàn)多個(gè)接口。((class) extends (class) implements (interface1,interface2…))
接口與接口之間是繼承關(guān)系:一個(gè)接口可以繼承另一個(gè)接口,并添加新的屬性和抽象方法,并且接口可以多繼承。((interface) extends (interface1,interface2…))
抽象類和接口的區(qū)別:
成員變量
抽象類能有變量也可以有常量
接口只能有常量
成員方法
抽象類可以有非抽象的方法,也可以有抽象的方法
接口只能有抽象的方法
構(gòu)造方法
-抽象類有構(gòu)造方法
-接口沒有構(gòu)造方法
類與抽象類和接口的關(guān)系
類與抽象類的關(guān)系是繼承 extends
類與接口的關(guān)系是實(shí)現(xiàn) implements
接口的思想特點(diǎn):
接口是對(duì)外暴露的規(guī)則;
接口是程序的功能擴(kuò)展;
接口的出現(xiàn)降低耦合性;(實(shí)現(xiàn)了模塊化開發(fā),定義好規(guī)則,每個(gè)人實(shí)現(xiàn)自己的模塊,大大提高了開發(fā)效率)
接口可以用來多實(shí)現(xiàn);
多個(gè)無關(guān)的類可以實(shí)現(xiàn)同一個(gè)接口;
一個(gè)類可以實(shí)現(xiàn)多個(gè)相互直接沒有關(guān)系的接口;
與繼承關(guān)系類似,接口與實(shí)現(xiàn)類之間存在多態(tài)性。
//運(yùn)動(dòng)員和教練的案例(下圖是思路分析) /* 籃球運(yùn)動(dòng)員和教練 乒乓球運(yùn)動(dòng)員和教練 現(xiàn)在籃球運(yùn)動(dòng)員和教練要出國訪問,需要學(xué)習(xí)英語 請根據(jù)你所學(xué)的知識(shí),分析出來哪些是類,哪些是抽象類,哪些是接口 */ interface SpeakEnglish { public abstract void speak(); } interface GoAboard{ public abstract void aboard(); } abstract class Person { private String name; private int age; public Person(){} public Person(String name,int age){ this.name = name; this.age = age; } public void setName(String name){ this.name = name; } public String getName(){ return name; } public void setAge(int age){ this.age = age; } public int getAge(){ return age; } //吃飯 public abstract void eat(); //睡覺 public void sleep(){ System.out.println("Zzz..."); } } //運(yùn)動(dòng)員 abstract class Player extends Person { public abstract void study(); } //教練 abstract class Coach extends Person { public abstract void teach(); } //籃球運(yùn)動(dòng)員 class BasketballPlayer extends Player implements SpeakEnglish,GoAboard{ public void eat(){ System.out.println(getAge() + "歲的" + getName() + "吃雞腿"); } public void study(){ System.out.println(getAge() + "歲的" + getName() + "學(xué)扣籃"); } public void speak(){ System.out.println(getAge() + "歲的" + getName() + " Say Hello World"); } public void aboard(){ System.out.println(getAge() + "歲的" + getName() + " Go Aboard"); } } //乒乓運(yùn)動(dòng)員 class PingPangPlayer extends Player{ public void eat(){ System.out.println(getAge() + "歲的" + getName() + "吃雞蛋"); } public void study(){ System.out.println(getAge() + "歲的" + getName() + "學(xué)扣球"); } } //籃球教練 class BasketballCoach extends Coach implements SpeakEnglish { public void eat(){ System.out.println(getAge() + "歲的" + getName() + "啃雞爪"); } public void teach(){ System.out.println(getAge() + "歲的" + getName() + "教扣籃"); } public void speak(){ System.out.println(getAge() + "歲的" + getName() + " Say Hello Java"); } public void aboard(){ System.out.println(getAge() + "歲的" + getName() + " Go Aboard"); } } //乒乓球教練 class PingPangCoach extends Coach{ public void eat(){ System.out.println(getAge() + "歲的" + getName() + "吃雞蛋皮"); } public void teach(){ System.out.println(getAge() + "歲的" + getName() + "教扣球"); } } class PlayerAndCoach { public static void main(String[] args) { //籃球運(yùn)動(dòng)員 BasketballPlayer bp = new BasketballPlayer(); bp.setName("郭艾倫"); bp.setAge(33); bp.eat(); bp.sleep(); bp.study(); bp.speak(); bp.aboard(); System.out.println("***********************"); //籃球教練 BasketballCoach bc = new BasketballCoach(); bc.setName("波波維奇"); bc.setAge(65); bc.eat(); bc.sleep(); bc.teach(); bc.speak(); bc.aboard(); System.out.println("***********************"); //多態(tài) Person p = new BasketballPlayer(); p.setName("Kobe Bryant"); p.setAge(33); p.eat(); p.sleep(); //p.study(); //p.speak(); BasketballPlayer bp2 = (BasketballPlayer)p; bp2.study(); bp2.speak(); bp2.aboard(); System.out.println("***********************"); } }內(nèi)部類
將一個(gè)類定義在另一個(gè)類里面,里面的那個(gè)類就稱為內(nèi)部類。內(nèi)部類的出現(xiàn),再次打破了Java單繼承的局限性。
訪問特點(diǎn):
內(nèi)部類可以直接訪問外部類的成員,包括私有成員。
外部類要訪問內(nèi)部類的成員,必須要建立內(nèi)部類的對(duì)象。
內(nèi)部類分類及共性:
共性:
內(nèi)部類仍然是一個(gè)獨(dú)立的類,在編譯之后會(huì)內(nèi)部類會(huì)被編譯成獨(dú)立的.class文件,但是前面冠以外部類的類名和$符號(hào)。
內(nèi)部類不能用普通的方式訪問。內(nèi)部類是外部類的一個(gè)成員,因此內(nèi)部類可以自由地訪問外部類的成員變量,無論是否是private的。
成員內(nèi)部類
在外部類中有成員變量和成員方法,成員內(nèi)部類就是把整個(gè)一個(gè)類作為了外部類的成員;
成員內(nèi)部類是定義在類中方法外的類;
創(chuàng)建對(duì)象的格式為:外部類名.內(nèi)部類名 對(duì)象名 = 外部類對(duì)象.內(nèi)部類對(duì)象;
成員內(nèi)部類之所以可以直接訪問外部類的成員,那是因?yàn)閮?nèi)部類中都持有一個(gè)外部類對(duì)象的引用:外部類名.this;
成員內(nèi)部類可以用的修飾符有final,abstract,public,private,protected,static.
靜態(tài)內(nèi)部類
靜態(tài)內(nèi)部類就是成員內(nèi)部類加上靜態(tài)修飾符static,定義在類中方法外。
在外部類中訪問靜態(tài)內(nèi)部類有兩種場景:
在外部類中訪問靜態(tài)內(nèi)部類中非靜態(tài)成員:外部類名.內(nèi)部類名 對(duì)象名 = 外部類名.內(nèi)部對(duì)象,需要通過創(chuàng)建對(duì)象訪問;
在外部類中訪問靜態(tài)內(nèi)部類中的靜態(tài)成員:同樣可以使用上面的格式進(jìn)行訪問,也可以直接使用外部類名.內(nèi)部類名.成員。
局部內(nèi)部類
局部內(nèi)部類是定義在方法中的類。
方法內(nèi)部類只能在定義該內(nèi)部類的方法內(nèi)實(shí)例化,不可以在此方法外對(duì)其實(shí)例化。
方法內(nèi)部類對(duì)象不能使用該內(nèi)部類所在方法的非final局部變量。
可以用于方法內(nèi)部類的修飾符有final,abstract;
靜態(tài)方法中的方法內(nèi)部類只能訪問外部的靜態(tài)成員。
匿名內(nèi)部類
匿名內(nèi)部類是內(nèi)部類的簡化寫法,是建立一個(gè)帶內(nèi)容的外部類或者接口的子類匿名對(duì)象。
前提:
內(nèi)部類可以繼承或?qū)崿F(xiàn)一個(gè)外部類或者接口。
格式:
new 外部類名或者接口名(){重寫方法};
通常在方法的形式參數(shù)是接口或者抽象類,并且該接口中的方法不超過三個(gè)時(shí),可以將匿名內(nèi)部類作為參數(shù)傳遞。
參考
Java集合的小抄 Java初學(xué)者必備
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/64401.html
摘要:面向?qū)ο笈c面向過程的區(qū)別要知道,二者并不是非此即彼,而是相輔相成的。而面向過程,則在微觀上對(duì)對(duì)象內(nèi)部進(jìn)行具體的實(shí)現(xiàn)。面向?qū)ο蟮娜筇匦哉f到面向?qū)ο?,就不得不說其三大特性封裝繼承和多態(tài)。封裝封裝是面向?qū)ο笞罨A(chǔ)的特性。 作者:伯特出處:github.com/ruicbAndroid/LoulanPlan聲明:本文出自伯特的《LoulanPlan》,轉(zhuǎn)載務(wù)必注明作者及出處。 剛學(xué)習(xí) Jav...
摘要:二面向?qū)ο蟾攀雒嫦蜻^程的設(shè)計(jì)思想和面向?qū)ο蟮脑O(shè)計(jì)思想我要吃魚香肉絲蓋飯面向過程我買菜我洗菜我切菜我放水我點(diǎn)火我做飯我炒菜。。。。 大家好,上次我們講過了樂字節(jié)Java編程之方法、調(diào)用、重載、遞歸,接下來我們將會(huì)進(jìn)入到Java封裝的內(nèi)容。Java編程語言發(fā)展,面向?qū)ο蠛皖悺?一、編程語言的發(fā)展 機(jī)器語言——直接由計(jì)算機(jī)的指令組成,指令、數(shù)據(jù)、地址都以0和1組成:可以被計(jì)算機(jī)直接識(shí)別并執(zhí)行...
摘要:是一種典型的面向?qū)ο缶幊陶Z言。這篇文章主要是來初步理解一下面向?qū)ο蟮乃季S為下面的內(nèi)容先給一個(gè)基礎(chǔ)。針對(duì)面向?qū)ο缶幊痰母鄡?nèi)容,會(huì)在后面的文章里面詳細(xì)解釋。他們都稱之為對(duì)象。之后,我們再用編程語言,把這種映射編寫出來,就是的面向?qū)ο缶幊汤病? showImg(https://segmentfault.com/img/remote/1460000012983458?w=900&h=500);...
摘要:眾多面向?qū)ο蟮木幊趟枷腚m不盡一致,但是無論哪種面向?qū)ο缶幊陶Z言都具有以下的共通功能。原型編程以類為中心的傳統(tǒng)面向?qū)ο缶幊蹋且灶悶榛A(chǔ)生成新對(duì)象。而原型模式的面向?qū)ο缶幊陶Z言沒有類這樣一個(gè)概念。 什么是面向?qū)ο??這個(gè)問題往往會(huì)問到剛畢業(yè)的新手or實(shí)習(xí)生上,也是往往作為一個(gè)技術(shù)面試的開頭題。在這里我們不去談如何答(fu)好(yan)問(guo)題(qu),僅談?wù)勎宜斫獾拿嫦驅(qū)ο蟆?從歷...
摘要:對(duì)象既是該類事物實(shí)實(shí)在在存在的個(gè)體。類與對(duì)象的關(guān)系圖類就是汽車汽車就是堆內(nèi)存中的對(duì)象。成員變量成員變量成員函數(shù)的車,輪胎數(shù)個(gè),跑起來了對(duì)象的創(chuàng)建創(chuàng)建對(duì)象中創(chuàng)建對(duì)象,使用關(guān)鍵字在堆內(nèi)存中開辟了空間,產(chǎn)生了一個(gè)實(shí)體。 聲明:本文首發(fā)于我的個(gè)人微信公眾號(hào)【Java編程社區(qū)】,查看更多文章與學(xué)習(xí)資源請移步我的公眾號(hào)Java編程社區(qū) 萬物皆對(duì)象 學(xué)習(xí)Java,我們都聽過這句話:萬物皆對(duì)象。那么什...
摘要:知識(shí)點(diǎn)總結(jié)面向?qū)ο笾R(shí)點(diǎn)總結(jié)面向?qū)ο竺嫦驅(qū)ο蟾拍钍窍鄬?duì)于面向過程而言,過程其實(shí)就是函數(shù),對(duì)象是將函數(shù)和屬性進(jìn)行了封裝。指向了該對(duì)象關(guān)鍵字代表對(duì)象。靜態(tài)變量所屬于類,所以也稱為類變量成員變量存在于堆內(nèi)存中。 Java知識(shí)點(diǎn)總結(jié)(面向?qū)ο螅?@(Java知識(shí)點(diǎn)總結(jié))[Java, Java面向?qū)ο骫 [toc] 面向?qū)ο蟾拍?是相對(duì)于面向過程而言,過程其實(shí)就是函數(shù),對(duì)象是將函數(shù)和屬性進(jìn)行了封...
閱讀 650·2023-04-26 02:59
閱讀 760·2023-04-25 16:02
閱讀 2230·2021-08-05 09:55
閱讀 3704·2019-08-30 15:55
閱讀 4814·2019-08-30 15:44
閱讀 1852·2019-08-30 13:02
閱讀 2270·2019-08-29 16:57
閱讀 2348·2019-08-26 13:35