日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

Java02继承

發(fā)布時(shí)間:2023/11/30 java 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java02继承 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

5繼承

5.1 類、超類和子類

關(guān)鍵字extends表示繼承。

Java中的繼承都是公用繼承,沒有C++中的私有繼承和保護(hù)繼承。

?

Super class ?Subclass ?來自于集合的術(shù)語

Base class ??Derived class

Parent class ?Child class

?

將通用的功能放在超類中,將具有特殊用途的方法放在子類中。

?

子類中可以覆蓋(override)超類中的方法。

子類不能直接訪問超類的私有域。

子類中調(diào)用超類方法:super.method()

C++中用 [超類名::方法]的方式調(diào)用超類方法。

?

因?yàn)樽宇惒荒茉L問超類私有域,

子類的構(gòu)造器中,第一條語句要用super(...)調(diào)用超類構(gòu)造器;

如果未提供super()語句,則調(diào)用默認(rèn)無參數(shù)的超類構(gòu)造器;

如果超類沒有默認(rèn)構(gòu)造器,則編譯出錯(cuò)。

?

C++中利用初始化列表語法調(diào)用超類構(gòu)造器。

?

繼承層次:

由一個(gè)公共超類派生出來的所有類的集合被稱為繼承層次(inheritance hierarchy。

從某個(gè)特定的類到其祖先的路徑被稱為該類的繼承鏈(inheritance chain

一個(gè)祖先類可以擁有多個(gè)子孫繼承鏈。

Java不支持多繼承。

?

多態(tài):

IS-A規(guī)則:子類的每個(gè)對(duì)象也是超類的對(duì)象。

置換法則,程序中出現(xiàn)超類對(duì)象的任何地方都可以用子類對(duì)象置換。

超類對(duì)象變量可以引用任何其子類對(duì)象。

不能將超類的引用賦給子類變量。

?

靜態(tài)綁定 static binding

對(duì)于private方法、static方法、final方法或者構(gòu)造器,編譯器可明確知道應(yīng)該調(diào)用哪個(gè)方法。

動(dòng)態(tài)綁定:

調(diào)用的方法依賴于隱式參數(shù)的實(shí)際類型,并且在運(yùn)行時(shí)實(shí)現(xiàn)動(dòng)態(tài)綁定。

虛擬機(jī)預(yù)先為每個(gè)類創(chuàng)建一個(gè)方法表(method table),其中列出了所有方法的簽名和實(shí)際調(diào)用的方法。真正調(diào)用的時(shí)候,虛擬機(jī)查找這個(gè)表。

?

覆蓋一個(gè)方法時(shí),子類方法不能低于超類方法的可見性。

?

阻止繼承:

Final類:不允許被擴(kuò)展的類。

Final方法:不允許被重寫的方法。

Final類中的方法自動(dòng)的稱為final方法。

Final域:常量。

Final的主要目的:確保它們不會(huì)在子類中改變語義。

String類是final類。

?

如果一個(gè)方法沒有被覆蓋并且很短,編譯器進(jìn)行內(nèi)聯(lián)(inlining)優(yōu)化處理。因?yàn)榉种мD(zhuǎn)移會(huì)擾亂指令預(yù)取策略。

?

強(qiáng)制類型轉(zhuǎn)換:

用一對(duì)圓括號(hào)將目標(biāo)類名括起來,置于需要轉(zhuǎn)換的目標(biāo)引用之前。

唯一原因:在暫時(shí)忽視對(duì)象的實(shí)際類型之后,使用對(duì)象的全部功能。

可以將子類引用賦給超類變量,但當(dāng)超類引用賦給子類變量時(shí),必須進(jìn)行類型轉(zhuǎn)換。

在類型轉(zhuǎn)換之前,進(jìn)行instanceof檢查。

綜上所述:

1、只能在繼承層次內(nèi)進(jìn)行類型轉(zhuǎn)換;

2、在將超類轉(zhuǎn)換成子類之前,使用instanceof進(jìn)行檢查。

?

在一般情況下,應(yīng)該盡量少用類型轉(zhuǎn)換和instanceof運(yùn)算符。

?

C++的類型轉(zhuǎn)換:Manager* boss = dynamic_cast<Manager*>(staff[1]);

?

抽象類:

包含一個(gè)或多個(gè)抽象方法的類必須聲明為抽象類。

抽象類可以包含具體數(shù)據(jù)和具體方法。

?

其子類如果實(shí)現(xiàn)部分抽象方法,則也需聲明為抽象類;

子類若實(shí)現(xiàn)全部抽象方法,則不必聲明為抽象方法。

?

類即使不包含抽象方法,也可以將其聲明為抽象類。

抽象類不能被實(shí)例化。

可以定義一個(gè)抽象類的對(duì)象變量,但是只能引用非抽象子類的對(duì)象。

?

C++中的抽象類:只要包含純虛函數(shù)的類就是抽象類。

?

編譯器只允許調(diào)用在類中聲明的方法。

?

受保護(hù)訪問:

允許子類的方法訪問超類的某個(gè)域,或希望超類的某些方法被子類訪問。

protected

最好的示例:Object類中的clone方法。

?

Private——對(duì)本類可見;

Public——對(duì)所有類可見;

Protected——對(duì)本包和所有子類可見;

默認(rèn)——對(duì)本包可見。

?

5.2 Object:所有類的超類

Object類型的變量可以引用任何類型的對(duì)象。

java中,只有基本類型(primitive types)不是對(duì)象。

所有數(shù)組類型都是對(duì)象,擴(kuò)展于Object類。

?

equals方法:

????public boolean equals( Object other);

Object中,檢測(cè)兩個(gè)對(duì)象變量是否有相同的引用(功能與==一致)。

在子類定義equals方法時(shí),首先調(diào)用超類的equals方法。如果檢測(cè)失敗,對(duì)象就不可能相等。如果超類中的域都相等,就需要比較子類中的實(shí)例域。

?

Java要求equals語法具有下面的性質(zhì):

自反性

對(duì)稱性

傳遞性

一致性

X.equals(null)應(yīng)該返回false

?

重寫符號(hào):方法前一行加@override

?

重寫equals方法步驟:

1、顯式參數(shù)命名為otherObject

2、檢測(cè)thisotherObject是否引用同一個(gè)對(duì)象;if (this == otherObject) return true;

3、檢測(cè)otherObject是否為空;if (otherObject == null) return false;

4、檢測(cè)otherObject是否屬于同一類。

a)?如果equals的語義在每個(gè)子類中有所改變,用getClass檢測(cè):

if (getClass() != otherObject.getClass()) return false;

b)?如果所有的子類都擁有統(tǒng)一語義,就使用instanceof檢測(cè):

if (!(otherObject instanceof ClassName)) return false;

5、otherObject轉(zhuǎn)換為相應(yīng)的類類型變量:ClassName other = (ClassName) otherObject;

6、對(duì)所有需要比較的域進(jìn)行比較。需在其中包含調(diào)用super.equals(other);

?

數(shù)組類型的域,用Arrays.equals(a1, a2)檢查是否相等。

?

hashcode方法:

public int hashcode();

定義在Object類中,每個(gè)對(duì)象都有一個(gè)默認(rèn)的散列碼,其值為對(duì)象的存儲(chǔ)地址。

Equals方法必須和hashcode方法一致,即如果a.equals(b)為真,則ab的散列碼必須相同。

?

Objects.hashCode(Object a); //如果為Null,返回0,否則返回a.hashcode()

Objects.hash(Object... objects); //返回所有對(duì)象的散列碼組合。

?

數(shù)組類型的域,用Arrays.hashCode(a)計(jì)算散列碼。

?

toString方法

Object類定義了toString()方法,打印輸出對(duì)象所屬的類名和散列碼。

絕大多數(shù)遵循格式:類的名字[域值]

getClass().getName()獲得類的名字。

只要對(duì)象與字符串通過 + 相連,就自動(dòng)調(diào)用對(duì)象的toString()方法。

System.out.println(x); //自動(dòng)調(diào)用xtoString()方法。

?

數(shù)組繼承了object類的toString方法。

如果想打印數(shù)組的內(nèi)容,用Arrays.toString(a);多維數(shù)組用Arrays.deepToString(a)

?

強(qiáng)烈建議為自定義的每一個(gè)類增加toString方法。

?

@SuppressWarnings(“unchecked”)

?

包裝器(wrapper) ?自動(dòng)裝箱(autoboxing) ?自動(dòng)拆箱

?

5.3 參數(shù)數(shù)量可變方法

最后一個(gè)參數(shù)為 類名... args,實(shí)際傳入一個(gè)數(shù)組。調(diào)用時(shí)可以傳入多個(gè)類對(duì)象,甚至一個(gè)類數(shù)組。


5.4 枚舉類

所有枚舉類型都是Enum類的子類。

比較時(shí),直接用==

?

5.6 反射

反射庫(reflection library)提供了一個(gè)非常豐富且精心設(shè)計(jì)的工具集,以便編寫能夠動(dòng)態(tài)操縱java代碼的程序。這項(xiàng)功能被大量地應(yīng)用于JavaBeans中,它是Java組件的體系結(jié)構(gòu)。

能夠分析類能力的程序稱為反射(reflective)。

?

在程序運(yùn)行期間,系統(tǒng)保存了所有已加載類的信息,虛擬機(jī)用這些信息選擇相應(yīng)的方法執(zhí)行。

保存這些信息的類被稱為Class


獲得類對(duì)象的三種方法:

1、Object類中的getClass()方法將會(huì)返回一個(gè)Class類型的實(shí)例。

2、還可以通過調(diào)用靜態(tài)方法forName獲得類名對(duì)應(yīng)的Class對(duì)象。

String className = “java.util.Date”;

Class c1 = Class.forName(className);

當(dāng)包含main()方法的類被加載時(shí),將會(huì)遞歸加載全部所需類。

一種逐步加載方法,調(diào)用Class.forName()手工加載其他類。

3、Class cl1 = Data.class;

?

可以利用==運(yùn)算符實(shí)現(xiàn)兩個(gè)類對(duì)象的比較操作。

?

類對(duì)象的newInstance()方法可以快速創(chuàng)建一個(gè)類的實(shí)例,調(diào)用的是默認(rèn)構(gòu)造函數(shù)。

String s = “java.util.Date”;

Object m = Class.forName(s).newInstance();

?

利用反射分析類的能力:

反射機(jī)制最重要的內(nèi)容——檢查類的結(jié)構(gòu)。

java.lang.reflect包中用三個(gè)類Field、Method、Constructor分別用于描述類的域、方法和構(gòu)造函數(shù)。

Class類中的getFileds()、getMethods()getConstructors()將返回public域、方法、構(gòu)造器數(shù)組,包括超類的公有成員。

Class類中的getDeclareFiels()、getDeclaredMehtods()、getDeclaredConstructors()返回全部域、方法、構(gòu)造器數(shù)組,不包括超類的公有成員。

?

public class ReflectionTest {public static void main(String[] args){String name;Scanner in = new Scanner(System.in);System.out.print("Enter class name: ");name = in.next();StringBuilder sb = new StringBuilder();try{Class c1 = Class.forName(name);Class superc1 = c1.getSuperclass();String modifiers =Modifier.toString(c1.getModifiers());if ( modifiers.length() > 0 )sb.append(modifiers + " ");sb.append("class" + name);if (superc1 != null && superc1 != Object.class)sb.append(" extends " + superc1.getName());sb.append("\n{\n");Constructor[]constructors = c1.getDeclaredConstructors();for (Constructor c : constructors){String cname = c.getName();sb.append("\t");String cmodifier =Modifier.toString(c.getModifiers());if (cmodifier.length() != 0)sb.append(cmodifier + " ");sb.append(cname+"(");Class[]cparameters = c.getParameterTypes();for ( int j = 0; j < cparameters.length; j++){if (j > 0)sb.append(",");sb.append(cparameters[j].getName());}sb.append(");\n");}sb.append("\n\n");Method[]methods = c1.getDeclaredMethods();for (Method m : methods){sb.append("\t");String mmodifier =Modifier.toString(m.getModifiers());if (mmodifier.length() != 0)sb.append(mmodifier + " ");String rtype = m.getReturnType().getName();sb.append(rtype + " " + m.getName() + "(");Class[]mparameters = m.getParameterTypes();for (int i = 0; i < mparameters.length; i++){if (i > 0)sb.append(",");sb.append(mparameters[i].getName());}sb.append(")\n");}sb.append("\n\n");Field[]fields = c1.getDeclaredFields();for (Field f : fields){sb.append("\t");String fmodifier =Modifier.toString(f.getModifiers());if( fmodifier.length() !=0 )sb.append(fmodifier + " ");Class type = f.getType();String tname = type.getName();String fname = f.getName();sb.append(tname + " " + fname + ";\n");}sb.append("}");System.out.println(sb);}catch(ClassNotFoundException e){e.printStackTrace();}} }

利用反射機(jī)制查看域值:

f.setAcessible(true);

f.get(obj);

利用反射機(jī)制修改域值:

f.get(obj, value);

?

編寫一個(gè)可供任意類使用的通用toString方法:

1、使用getDeclaredFileds獲得所有數(shù)據(jù)域;

2、使用setAccessible將所有的域設(shè)置為可訪問的;

3、對(duì)每個(gè)域,獲得名字和值。

?

setAccessible方法是AccessibleObject類中的一個(gè)方法,是Filed、Method、Constructor類的公共超類。

?

Method對(duì)象的invoke方法,允許調(diào)用包裝在當(dāng)前Method對(duì)象中的方法。

方法簽名:

Object invoke(Object obj, Object... args);

第一個(gè)參數(shù)為具體對(duì)象,其余為這個(gè)方法的參數(shù)。

對(duì)于靜態(tài)方法,第一個(gè)參數(shù)設(shè)置為NULL。

Invoke的參數(shù)和返回值必須是Object類型的。

使用反射獲得方法指針的代碼要比僅僅直接調(diào)用方法明顯慢一些。

?

5.7 繼承設(shè)計(jì)的技巧

1、將公共操作和域放在超類;

2、不要使用受保護(hù)的域;

3、使用繼承體現(xiàn)IS-A關(guān)系;

4、除非所有繼承的方法都有意義,否則不要使用繼承;

5、在覆蓋原方法時(shí),不要改變預(yù)期的行為;

6、使用多態(tài);

7、不要過多的使用反射——對(duì)編寫系統(tǒng)程序及其有用,不適用于應(yīng)用程序的編寫。

?

總結(jié)

以上是生活随笔為你收集整理的Java02继承的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。