Java超詳細(xì)講解繼承和多態(tài)的使用
繼承和多態(tài)
學(xué)習(xí)繼承、組合、多態(tài)
1、繼承
1.1、繼承概念
專門用來進(jìn)行共性抽取,實(shí)現(xiàn)代碼復(fù)用。 它允許程序員在保持原有類特 性的基礎(chǔ)上進(jìn)行擴(kuò)展,增加新功能,這樣產(chǎn)生新的類,稱派生類。
1.2、繼承的語法
在Java中如果要表示類之間的繼承關(guān)系,需要借助extends關(guān)鍵字
class Animal{
public String name;
public int age;
public String sex;
public void eat(){
System.out.println(this.name+"cat::eat()!");
}
public void sleep(){
System.out.println(this.name+"睡覺!");
}
}
/**
* 繼承 其實(shí)就是對(duì)共性的抽取 從而達(dá)到了代碼的復(fù)用
*/
class Cat extends Animal{
public void mew(){
System.out.println(this.name+"cat::mew()!");
}
}
class Dog extends Animal{
public void bark(){
System.out.println("dog::bark()!");
}
}
public class TestDemo {
public static void main(String[] args) {
Cat cat = new Cat();
cat.name = "咪咪";
cat.sleep();
cat.eat();
cat.mew();
}
}注意:
1. 子類會(huì)將父類中的成員變量或者成員方法繼承到子類中了
2. 子類繼承父類之后,盡量新添加自己特有的成員,體現(xiàn)出與基類的不同,否則就沒有必要繼承了
1.3、父類成員的訪問
1.31、子類和父類不存在同名成員變量
public class Base {
int a;
int b;
}
public class Derived extends Base{
int c;
public void method(){
a = 10; // 訪問從父類中繼承下來的a
b = 20; // 訪問從父類中繼承下來的b
c = 30; // 訪問子類自己的c
}
}
1.32、子類和父類成員變量同名
class Base {
public int a = 1;
public int b = 2;
public void method(){
System.out.println("BASE::TEST()");
}
}
class Derived extends Base{
public int a = 3;
public int d = 4;
public void method2(){
System.out.println("Derived::method2()");
}
public void test(){
method2();
method();
/*System.out.println(a);//如果重名類 優(yōu)先訪問自己的
System.out.println(super.a);//寫代碼的時(shí)候 讓這個(gè)代碼更已讀
System.out.println(this.b);
System.out.println(d);*/
}
}
public class TestDemo2 {
public static void main(String[] args) {
Derived derived = new Derived();
derived.test();
}
}
1、如果訪問的成員變量子類中有,訪問自己的成員變量。
2、如果訪問的成員變量子類中無,則訪問父類繼承下來的,如果父類也沒有定義,則編譯報(bào)錯(cuò)。
3、如果訪問的成員變量與父類中成員變量同名,則優(yōu)先訪問自己的,即:子類將父類同名成員隱藏了。
4、成員變量訪問遵循就近原則,自己有優(yōu)先自己的,如果沒有則向父類中找。
比如:你和你父親各自有一款相同的手機(jī),平時(shí)使用時(shí)你肯定優(yōu)先用自己的,如果自己手機(jī)沒電了,你才會(huì)考慮使用父親的。
1.33、成員方法名字不同
public class Base {
public void methodA(){
System.out.println("Base中的methodA()");
}
}
public class Derived extends Base{
public void methodB(){
System.out.println("Derived中的methodB()方法");
}
public void methodC(){
methodB(); // 訪問子類自己的methodB()
methodA(); // 訪問父類繼承的methodA()
// methodD(); // 編譯失敗,在整個(gè)繼承體系中沒有發(fā)現(xiàn)方法methodD()
}
}
總結(jié):成員方法沒有同名時(shí),在子類方法中或者通過子類對(duì)象訪問方法時(shí),則優(yōu)先訪問自己的,自己沒有時(shí) 再到父類中找,如果父類中也沒有則報(bào)錯(cuò)。
1.34、 成員方法名字相同
public class Base {
public void methodA(){
System.out.println("Base中的methodA()");
}
public void methodB(){
System.out.println("Base中的methodB()");
}
}
public class Derived extends Base{
public void methodA(int a) {
System.out.println("Derived中的method(int)方法");
}
public void methodB(){
System.out.println("Derived中的methodB()方法");
}
public void methodC(){
methodA(); // 沒有傳參,訪問父類中的methodA()
methodA(20); // 傳遞int參數(shù),訪問子類中的methodA(int)
methodB(); // 直接訪問,則永遠(yuǎn)訪問到的都是子類中的methodB(),基類的無法訪問到
}
}通過子類對(duì)象訪問父類與子類中不同名方法時(shí),優(yōu)先在子類中找,找到則訪問,否則在父類中找,找到 則訪問,否則編譯報(bào)錯(cuò)。 通過派生類對(duì)象訪問父類與子類同名方法時(shí),如果父類和子類同名方法的參數(shù)列表不同(重載),根據(jù)調(diào)用 方法適傳遞的參數(shù)選擇合適的方法訪問,如果沒有則報(bào)錯(cuò);如果父類和子類同名方法的原型一致,則只能訪問到子類的,父類的無法通過派生類對(duì)象直接訪問到。 問題:如果子類中存在與父類中相同的成員時(shí),那如何在子類中訪問父類相同名稱的成員呢?
1.4、super關(guān)鍵字
public class Base {
int a;
int b;
public void methodA(){
System.out.println("Base中的methodA()");
}
public void methodB(){
System.out.println("Base中的methodB()");
}
}
public class Derived extends Base{
int a; // 與父類中成員變量同名且類型相同
char b; // 與父類中成員變量同名但類型不同
// 與父類中methodA()構(gòu)成重載
public void methodA(int a) {
System.out.println("Derived中的method()方法");
}
// 與基類中methodB()構(gòu)成重寫
public void methodB(){
System.out.println("Derived中的methodB()方法");
}
public void methodC(){
// 對(duì)于同名的成員變量,直接訪問時(shí),訪問的都是子類的
a = 100; // 等價(jià)于: this.a = 100;
b = 101; // 等價(jià)于: this.b = 101;
// 注意:this是當(dāng)前對(duì)象的引用
// 訪問父類的成員變量時(shí),需要借助super關(guān)鍵字
// super是獲取到子類對(duì)象中從基類繼承下來的部分
super.a = 200;
super.b = 201;
// 父類和子類中構(gòu)成重載的方法,直接可以通過參數(shù)列表區(qū)分清訪問父類還是子類方法
methodA(); // 沒有傳參,訪問父類中的methodA()
methodA(20); // 傳遞int參數(shù),訪問子類中的methodA(int)
// 如果在子類中要訪問重寫的基類方法,則需要借助super關(guān)鍵字
methodB(); // 直接訪問,則永遠(yuǎn)訪問到的都是子類中的methodB(),基類的無法訪問到
super.methodB(); // 訪問基類的methodB()
}
}【注意事項(xiàng)】
1. 只能在非靜態(tài)方法中使用
2. 在子類方法中,訪問父類的成員變量和方法。
1.5、子類構(gòu)造方法
父子父子,先有父再有子,即:子類對(duì)象構(gòu)造時(shí),需要先調(diào)用基類構(gòu)造方法,然后執(zhí)行子類的構(gòu)造方法。
public class Base {
public Base(){
System.out.println("Base()");
}
}
public class Derived extends Base{
public Derived(){
super(); // 注意子類構(gòu)造方法中默認(rèn)會(huì)調(diào)用基類的無參構(gòu)造方法:super(),
// 用戶沒有寫時(shí),編譯器會(huì)自動(dòng)添加,而且super()必須是子類構(gòu)造方法中第一條語句,
// 并且只能出現(xiàn)一次
System.out.println("Derived()");
}
}
public class Test {
public static void main(String[] args) {
Derived d = new Derived();
}
}
結(jié)果打?。?br />Base()
Derived()
在子類構(gòu)造方法中,并沒有寫任何關(guān)于基類構(gòu)造的代碼,但是在構(gòu)造子類對(duì)象時(shí),先執(zhí)行基類的構(gòu)造方法,然后執(zhí)行子類的構(gòu)造方法,因?yàn)椋鹤宇悓?duì)象中成員是有兩部分組成的,基類繼承下來的以及子類新增加的部分 。父子父子 肯定是先有父再有子,所以在構(gòu)造子類對(duì)象時(shí)候 ,先要調(diào)用基類的構(gòu)造方法,將從基類繼承下來的成員構(gòu)造完整,然后再調(diào)用子類自己的構(gòu)造方法,將子類自己新增加的成員初始化完整 。
注意:
1. 若父類顯式定義無參或者默認(rèn)的構(gòu)造方法,在子類構(gòu)造方法第一行默認(rèn)有隱含的super()調(diào)用,即調(diào)用基類構(gòu)
造方法
2. 如果父類構(gòu)造方法是帶有參數(shù)的,此時(shí)編譯器不會(huì)再給子類生成默認(rèn)的構(gòu)造方法,此時(shí)需要用戶為子類顯式
定義構(gòu)造方法,并在子類構(gòu)造方法中選擇合適的父類構(gòu)造方法調(diào)用,否則編譯失敗。
3. 在子類構(gòu)造方法中,super(…)調(diào)用父類構(gòu)造時(shí),必須是子類構(gòu)造函數(shù)中第一條語句。
4. super(…)只能在子類構(gòu)造方法中出現(xiàn)一次,并且不能和this同時(shí)出現(xiàn)
1.6、super和this
【相同點(diǎn)】
1. 都是Java中的關(guān)鍵字
2. 只能在類的非靜態(tài)方法中使用,用來訪問非靜態(tài)成員方法和字段
3. 在構(gòu)造方法中調(diào)用時(shí),必須是構(gòu)造方法中的第一條語句,并且不能同時(shí)存在
【不同點(diǎn)】
1. this是當(dāng)前對(duì)象的引用,當(dāng)前對(duì)象即調(diào)用實(shí)例方法的對(duì)象,super相當(dāng)于是子類對(duì)象中從父類繼承下來部分成員的引用
2. 在非靜態(tài)成員方法中,this用來訪問本類的方法和屬性,super用來訪問父類繼承下來的方法和屬性
3. this是非靜態(tài)成員方法的一個(gè)隱藏參數(shù),super不是隱藏的參數(shù)
4. 成員方法中直接訪問本類成員時(shí),編譯之后會(huì)將this還原,即本類非靜態(tài)成員都是通過this來訪問的;在子類中如果通過super訪問父類成員,編譯之后在字節(jié)碼層面super實(shí)際是不存在的
5. 在構(gòu)造方法中:this(…)用于調(diào)用本類構(gòu)造方法,super(…)用于調(diào)用父類構(gòu)造方法,兩種調(diào)用不能同時(shí)在構(gòu)造方法中出現(xiàn)
6. 構(gòu)造方法中一定會(huì)存在super(…)的調(diào)用,用戶沒有寫編譯器也會(huì)增加,但是this(…)用戶不寫則沒有
1.7、初始化
class Person {
public String name;
public int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
System.out.println("構(gòu)造方法執(zhí)行");
}
{
System.out.println("實(shí)例代碼塊執(zhí)行");
}
static {
System.out.println("靜態(tài)代碼塊執(zhí)行");
}
}
public class TestDemo {
public static void main(String[] args) {
Person person1 = new Person("bit",10);
System.out.println("============================");
Person person2 = new Person("gaobo",20);
}
}執(zhí)行結(jié)果:
靜態(tài)代碼塊執(zhí)行
實(shí)例代碼塊執(zhí)行
構(gòu)造方法執(zhí)行
============================
實(shí)例代碼塊執(zhí)行
構(gòu)造方法執(zhí)行
注意:
1. 靜態(tài)代碼塊先執(zhí)行,并且只執(zhí)行一次,在類加載階段執(zhí)行
2. 當(dāng)有對(duì)象創(chuàng)建時(shí),才會(huì)執(zhí)行實(shí)例代碼塊,實(shí)例代碼塊執(zhí)行完成后,最后構(gòu)造方法執(zhí)行
繼承關(guān)系上的執(zhí)行順序:
1、父類靜態(tài)代碼塊優(yōu)先于子類靜態(tài)代碼塊執(zhí)行,且是最早執(zhí)行
2、父類實(shí)例代碼塊和父類構(gòu)造方法緊接著執(zhí)行
3、子類的實(shí)例代碼塊和子類構(gòu)造方法緊接著再執(zhí)行
4、第二次實(shí)例化子類對(duì)象時(shí),父類和子類的靜態(tài)代碼塊都將不會(huì)再執(zhí)行
1.8、protected關(guān)鍵字
// 為了掩飾基類中不同訪問權(quán)限在子類中的可見性,為了簡單類B中就不設(shè)置成員方法了
// extend01包中
public class B {
private int a;
protected int b;
public int c;
int d;
}
// extend01包中
// 同一個(gè)包中的子類
public class D extends B{
public void method(){
// super.a = 10; // 編譯報(bào)錯(cuò),父類private成員在相同包子類中不可見
super.b = 20; // 父類中protected成員在相同包子類中可以直接訪問
super.c = 30; // 父類中public成員在相同包子類中可以直接訪問
super.d = 40; // 父類中默認(rèn)訪問權(quán)限修飾的成員在相同包子類中可以直接訪問
}
}
// extend02包中
// 不同包中的子類
public class C extends B {
public void method(){
// super.a = 10; // 編譯報(bào)錯(cuò),父類中private成員在不同包子類中不可見
super.b = 20; // 父類中protected修飾的成員在不同包子類中可以直接訪問
super.c = 30; // 父類中public修飾的成員在不同包子類中可以直接訪問
//super.d = 40; // 父類中默認(rèn)訪問權(quán)限修飾的成員在不同包子類中不能直接訪問
}
}
// extend02包中
// 不同包中的類
public class TestC {
public static void main(String[] args) {
C c = new C();
c.method();
// System.out.println(c.a); // 編譯報(bào)錯(cuò),父類中private成員在不同包其他類中不可見
// System.out.println(c.b); // 父類中protected成員在不同包其他類中不能直接訪問
System.out.println(c.c); // 父類中public成員在不同包其他類中可以直接訪問
// System.out.println(c.d); // 父類中默認(rèn)訪問權(quán)限修飾的成員在不同包其他類中不能直接訪問
}
}注意:父類中private成員變量隨時(shí)在子類中不能直接訪問,但是也繼承到子類中了
1.9、繼承方式

1.10、final關(guān)鍵字
final關(guān)鍵可以用來修飾變量、成員方法以及類。
1. 修飾變量或字段,表示常量(即不能修改)
2. 修飾類:表示此類不能被繼承
2、繼承與組合
組合表示對(duì)象之間的關(guān)系
// 輪胎類
class Tire{
// ...
}
// 發(fā)動(dòng)機(jī)類
class Engine{
// ...
}
// 車載系統(tǒng)類
class VehicleSystem{
// ...
}
class Car{
private Tire tire; // 可以復(fù)用輪胎中的屬性和方法
private Engine engine; // 可以復(fù)用發(fā)動(dòng)機(jī)中的屬性和方法
private VehicleSystem vs; // 可以復(fù)用車載系統(tǒng)中的屬性和方法
// ...
}
// 奔馳是汽車
class Benz extend Car{
// 將汽車中包含的:輪胎、發(fā)送機(jī)、車載系統(tǒng)全部繼承下來
}3、多態(tài)
3.1、多態(tài)概念
通俗來說,就是多種形態(tài),具體點(diǎn)就是去完成某個(gè)行為,當(dāng)不同的對(duì)象去完成時(shí)會(huì)產(chǎn)生出不同 的狀態(tài)。
3.2、多態(tài)實(shí)現(xiàn)條件
1. 必須在繼承體系下
2. 子類必須要對(duì)父類中方法進(jìn)行重寫
3. 通過父類的引用調(diào)用重寫的方法
public class Animal {
String name;
int age;
public Animal(String name, int age){
this.name = name;
this.age = age;
}
public void eat(){
System.out.println(name + "吃飯");
}
}
public class Cat extends Animal{
public Cat(String name, int age){
super(name, age);
}
@Override
public void eat(){
System.out.println(name+"吃魚~~~");
}
}
public class Dog extends Animal {
public Dog(String name, int age){
super(name, age);
}
@Override
public void eat(){
System.out.println(name+"吃骨頭~~~");
}
}
///分割線//
public class TestAnimal {
// 編譯器在編譯代碼時(shí),并不知道要調(diào)用Dog 還是 Cat 中eat的方法
// 等程序運(yùn)行起來后,形參a引用的具體對(duì)象確定后,才知道調(diào)用那個(gè)方法
// 注意:此處的形參類型必須時(shí)父類類型才可以
public static void eat(Animal a){
a.eat();
}
public static void main(String[] args) {
Cat cat = new Cat("元寶",2);
Dog dog = new Dog("小七", 1);
eat(cat);
eat(dog);
}
}運(yùn)行結(jié)果:
元寶吃魚~~~
元寶正在睡覺
小七吃骨頭~~~
小七正在睡覺
3.3、重寫
重寫(override):也稱為覆蓋。重寫是子類對(duì)父類非靜態(tài)、非private修飾,非final修飾,非構(gòu)造方法等的實(shí)現(xiàn)過程進(jìn)行重新編寫, 返回值和形參都不能改變。即外殼不變,核心重寫!重寫的好處在于子類可以根據(jù)需要,定義特定于自己的行為。 也就是說子類能夠根據(jù)需要實(shí)現(xiàn)父類的方法。
1. 子類在重寫父類的方法時(shí),一般必須與父類方法原型一致:修飾符 返回值類型 方法名(參數(shù)列表) 要完全一致
2. JDK7以后,被重寫的方法返回值類型可以不同,但是必須是具有父子關(guān)系的
訪問權(quán)限不能比父類中被重寫的方法的訪問權(quán)限更低。例如:如果父類方法被public修飾,則子類中重寫該方法就不能聲明為 protected
3. 父類被static、private修飾的方法、構(gòu)造方法都不能被重寫。
子類和父類在同一個(gè)包中,那么子類可以重寫父類所有方法,除了聲明為 private 和 final 的方法。
4. 子類和父類不在同一個(gè)包中,那么子類只能夠重寫父類的聲明為 public 和 protected 的非 final 方法。
5. 重寫的方法, 可以使用 @Override 注解來顯式指定. 有了這個(gè)注解能幫我們進(jìn)行一些合法性校驗(yàn). 例如不小心將方法名字拼寫錯(cuò)了 (比如寫成 aet), 那么此時(shí)編譯器就會(huì)發(fā)現(xiàn)父類中沒有 aet 方法, 就會(huì)編譯報(bào)錯(cuò), 提示無法構(gòu)成重寫.
重載與重寫區(qū)別:

方法重載是一個(gè)類的多態(tài)性表現(xiàn),而方法重寫是子類與父類的一種多態(tài)性表現(xiàn)。
3.4、向上轉(zhuǎn)型和向下轉(zhuǎn)型
向上轉(zhuǎn)型:實(shí)際就是創(chuàng)建一個(gè)子類對(duì)象,將其當(dāng)成父類對(duì)象來使用。
語法格式:父類類型 對(duì)象名 = new 子類類型()
【使用場景】
1. 直接賦值
2. 方法傳參
3. 方法返回
public class TestAnimal {
// 2. 方法傳參:形參為父類型引用,可以接收任意子類的對(duì)象
public static void eatFood(Animal a){
a.eat();
}
// 3. 作返回值:返回任意子類對(duì)象
public static Animal buyAnimal(String var){
if("狗" == var){
return new Dog("狗狗",1);
}else if("貓" == var){
return new Cat("貓貓", 1);
}else{
return null;
}
}
public static void main(String[] args) {
Animal cat = new Cat("元寶",2); // 1. 直接賦值:子類對(duì)象賦值給父類對(duì)象
Dog dog = new Dog("小七", 1);
eatFood(cat);
eatFood(dog);
Animal animal = buyAnimal("狗");
animal.eat();
animal = buyAnimal("貓");
animal.eat();
}
}將一個(gè)子類對(duì)象經(jīng)過向上轉(zhuǎn)型之后當(dāng)成父類方法使用,再無法調(diào)用子類的方法,但有時(shí)候可能需要調(diào)用子類特有的
方法,此時(shí):將父類引用再還原為子類對(duì)象即可,即向下轉(zhuǎn)換。

public class TestAnimal {
public static void main(String[] args) {
Cat cat = new Cat("元寶",2);
Dog dog = new Dog("小七", 1);
// 向上轉(zhuǎn)型
Animal animal = cat;
animal.eat();
animal = dog;
animal.eat();
// 編譯失敗,編譯時(shí)編譯器將animal當(dāng)成Animal對(duì)象處理
// 而Animal類中沒有bark方法,因此編譯失敗
// animal.bark();
// 向上轉(zhuǎn)型
// 程序可以通過編程,但運(yùn)行時(shí)拋出異常---因?yàn)椋篴nimal實(shí)際指向的是狗
// 現(xiàn)在要強(qiáng)制還原為貓,無法正常還原,運(yùn)行時(shí)拋出:ClassCastException
cat = (Cat)animal;
cat.mew();
// animal本來指向的就是狗,因此將animal還原為狗也是安全的
dog = (Dog)animal;
dog.bark();
}
}
向下轉(zhuǎn)型用的比較少,而且不安全,萬一轉(zhuǎn)換失敗,運(yùn)行時(shí)就會(huì)拋異常。Java中為了提高向下轉(zhuǎn)型的安全性,引入
了 instanceof ,如果該表達(dá)式為true,則可以安全轉(zhuǎn)換。
public class TestAnimal {
public static void main(String[] args) {
Cat cat = new Cat("元寶",2);
Dog dog = new Dog("小七", 1);
// 向上轉(zhuǎn)型
Animal animal = cat;
animal.eat();
animal = dog;
animal.eat();
if(animal instanceof Cat){
cat = (Cat)animal;
cat.mew();
}
if(animal instanceof Dog){
dog = (Dog)animal;
dog.bark();
}
}
}
3.5、多態(tài)優(yōu)缺點(diǎn)
【使用多態(tài)的好處】
1. 能夠降低代碼的 “圈復(fù)雜度”, 避免使用大量的 if - else
就曉得了什么叫 “圈復(fù)雜度” ?那么我們來對(duì)比一下
這是if-else分支語句:
public static void drawShapes() {
Rect rect = new Rect();
Cycle cycle = new Cycle();
Flower flower = new Flower();
String[] shapes = {"cycle", "rect", "cycle", "rect", "flower"};
for (String shape : shapes) {
if (shape.equals("cycle")) {
cycle.draw();
} else if (shape.equals("rect")) {
rect.draw();
} else if (shape.equals("flower")) {
flower.draw();
}
}
}如果使用使用多態(tài):
public static void drawShapes() {
// 我們創(chuàng)建了一個(gè) Shape 對(duì)象的數(shù)組.
Shape[] shapes = {new Cycle(), new Rect(), new Cycle(),
new Rect(), new Flower()};
for (Shape shape : shapes) {
shape.draw();
}
}2. 可擴(kuò)展能力更強(qiáng)
如果要新增一種新的形狀, 使用多態(tài)的方式代碼改動(dòng)成本也比較低.
class Triangle extends Shape {
@Override
public void draw() {
System.out.println("△");
}
}
對(duì)于類的調(diào)用者來說(drawShapes方法), 只要?jiǎng)?chuàng)建一個(gè)新類的實(shí)例就可以了, 改動(dòng)成本很低. 而對(duì)于不用多態(tài)的情況, 就要把drawShapes 中的 if - else 進(jìn)行一定的修改, 改動(dòng)成本更高.
多態(tài)缺陷:代碼的運(yùn)行效率降低。
3.6、避免在構(gòu)造方法中調(diào)用重寫的方法
我們創(chuàng)建兩個(gè)類, B 是父類, D 是子類. D 中重寫 func 方法. 并且在 B 的構(gòu)造方法中調(diào)用 func
class B {
public B() {
// do nothing
func();
}
public void func() {
System.out.println("B.func()");
}
}
class D extends B {
private int num = 1;
@Override
public void func() {
System.out.println("D.func() " + num);
}
}
public class Test {
public static void main(String[] args) {
D d = new D();
}
}
執(zhí)行結(jié)果
D.func() 0
1. 構(gòu)造 D 對(duì)象的同時(shí), 會(huì)調(diào)用 B 的構(gòu)造方法.
2. B 的構(gòu)造方法中調(diào)用了 func 方法, 此時(shí)會(huì)觸發(fā)動(dòng)態(tài)綁定, 會(huì)調(diào)用到 D 中的 func此時(shí) D 對(duì)象自身還沒有構(gòu)造, 此時(shí) num 處在未初始化的狀態(tài), 值為 0.
結(jié)論: “用盡量簡單的方式使對(duì)象進(jìn)入可工作狀態(tài)”, 盡量不要在構(gòu)造器中調(diào)用方法(如果這個(gè)方法被子類重寫, 就會(huì)觸 發(fā)動(dòng)態(tài)綁定,
但是此時(shí)子類對(duì)象還沒構(gòu)造完成), 可能會(huì)出現(xiàn)一些隱藏的但是又極難發(fā)現(xiàn)的問題.
到此這篇關(guān)于Java超詳細(xì)講解繼承和多態(tài)的使用的文章就介紹到這了,更多相關(guān)Java繼承和多態(tài)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
IDEA導(dǎo)入外部項(xiàng)目報(bào)Error:java: 無效的目標(biāo)發(fā)行版: 11的解決方法
這篇文章主要介紹了IDEA導(dǎo)入外部項(xiàng)目報(bào)Error:java: 無效的目標(biāo)發(fā)行版: 11,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-09-09
Java數(shù)據(jù)結(jié)構(gòu)超詳細(xì)分析二叉搜索樹
二叉搜索樹是以一棵二叉樹來組織的。每個(gè)節(jié)點(diǎn)是一個(gè)對(duì)象,包含的屬性有l(wèi)eft,right,p和key,其中,left指向該節(jié)點(diǎn)的左孩子,right指向該節(jié)點(diǎn)的右孩子,p指向該節(jié)點(diǎn)的父節(jié)點(diǎn),key是它的值2022-03-03
Java圖形用戶界面設(shè)計(jì)(Swing)的介紹
看到多數(shù)人提到 Java 就以為是網(wǎng)絡(luò)開發(fā),其實(shí)不是這樣的,Java 也可以開發(fā)應(yīng)用程序,而且可以開發(fā)出漂亮的圖形用戶界面的應(yīng)用程序,因此,我寫下這篇文章,希望能帶你進(jìn)入 Java 圖形用戶界面設(shè)計(jì)之門。2016-07-07
java EasyExcel實(shí)現(xiàn)動(dòng)態(tài)列解析和存表
這篇文章主要為大家介紹了java EasyExcel實(shí)現(xiàn)動(dòng)態(tài)列解析和存表示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-06-06
springboot 中異步任務(wù),定時(shí)任務(wù),郵件任務(wù)詳解
這篇文章主要介紹了springboot 與異步任務(wù),定時(shí)任務(wù),郵件任務(wù),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-09-09
Java界面編程實(shí)現(xiàn)界面跳轉(zhuǎn)
這篇文章主要為大家詳細(xì)介紹了Java界面編程實(shí)現(xiàn)界面跳轉(zhuǎn),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-06-06

