1. 程式人生 > >Java多型中過載方法引數分別為父類和子類時的疑惑

Java多型中過載方法引數分別為父類和子類時的疑惑

問題:

程式碼如下: 
class A {  
    public String show(D obj){  
           return ("A and D");  
    }   
    public String show(A obj){  
           return ("A and A");  
    } 
}   
class B extends A{ 
    public String show(A obj){  
           return ("B and A");  
    }   
    public String show(B obj){  
           return ("B and B");  
    } 
}  
class C extends B{}   
class D extends B{} 

public class MultiTest{ 
public static void main(String[] args){ 
        A ab = new B();  
        B b = new B();  
        C c = new C(); 
        System.out.println(ab.show(b));   
        System.out.println(ab.show(c)); 
} 
} 

執行程式碼結果如下: 
B and A 
B and A 

為什麼不是 

B and B 
B and B 

網友們給出的各種解答,挺好的

網友1、
A ab = new B(); 
這裡ab的引用型別是A,但是它指向的記憶體是型別為B的一個例項

想對ab進行方法呼叫,你呼叫的方法都必須在 class A裡面有的才行(因為你的引用型別為A)
這裡 class A有show(A obj) show(D obj)著兩個方法

ab.show(b) 在class A中沒有找到型別匹配的方法,但是對b進行型別提升後,可以找到 show(A obj)方法,同理 ab.show(c)也是show(A obj)方法;但是ab記憶體地址指向一個型別為B記憶體空間,如果class B Override 了 class A的show(A obj)方法,則呼叫B的方法,反之,則呼叫A自己的方法

可以猜測  D d = new D();  ab.show(d)的結果是 A and D
如果註釋掉 class A的  show(A obj)方法, ab.show(b)  ab.show(c)都會出錯。

這裡你只要記住,能呼叫那些方法,由引用型別決定,具體執行情況,由實際記憶體物件型別決定

網友2、

Override 是多型,由執行時實際類決定,所以呼叫的是B類的方法而不是A類的方法。 
Overload 是由編譯器在編譯時決定的,因為 ab 的宣告型別為 A,所以會呼叫 show(A obj) 方法,編譯型別一致。

網友3、

Java 執行方法時,是動態匹配的,在執行時才會決定用哪個方法。A ab = new B(); 你呼叫ab.show(b)時,會根據物件的型別A,去找方法,A中的show(A obj)匹配上,但是此方法在B中被覆蓋了,所以會呼叫B中的show(A obj)。 
如果將程式碼改為:B ab = new B();,這個執行時:ab.show(b)會直接呼叫show(B obj);ab.show(c)會將c向上轉型一次,然後呼叫show(B obj)。 
這樣的話最後的結果就會是: 
                 B and B 
                 B and B 
總結: 
    java執行方法時,會根據物件的型別得到相應的方法,如果不存在編譯時會報錯,真正執行時,會動態去匹配,如果真正的物件是子類的話,且此方法在子類中被覆蓋的話,就會執行子類方法。 
    java型別匹配時,如果不能匹配的話就做向上型別轉換,轉換為父類,直到能夠匹配為止,若一直不能匹配在編譯時會報錯。

網友4、

這個涉及到了java的多型中的向上轉型,簡單來說,父類引用生成子類物件,那這個引用只能呼叫在父類中已經定義過的屬性和方法,而對子類自己新定義的屬性和方法則不能訪問。比如你這裡的A ab=new B();,ab是一個父類引用,之後執行ab.show(b),這時ab先從父類中查詢方法,與之匹配的只有show(A obj)方法,而且發現子類重寫了該方法,這時動態連結到子類的show(A obj)方法。 
假如你執行b.show(c),這裡,b中有show(A obj)方法和show(B obj)方法,繼承層次為C->B->A,根據過載的最近匹配原則,會呼叫show(B obj)方法。

自己在eclipse中寫了上面的程式碼,利用eclipse的自動提示方法呼叫功能,看了下對方法的提示,如下圖:

可以看到,提示的是A類中的兩個方法,而不是B類中的兩個方法,編譯的時候看的是引用型別,執行的時候呼叫的是實際型別。


相關推薦

Java過載方法引數分別疑惑

問題: 程式碼如下: class A { public String show(D obj){ return ("A and D"); } public String show(A obj){

Java的向上轉型向下轉型

向上轉型:將一個父類的引用指向一個子類物件,稱為向上轉型,自動進行型別轉換     用法: Father f = new Son(); 向下轉型:子類引用指向父類引用的子類物件  通俗的說就是子類例項物件賦值給父類引用,然後父類引用又要賦值給子類引用,這個過程就是向下轉型

第十一章:Java的引用型別轉換以及抽象

引用型別轉換 1.向上型別轉換(隱式/自動型別轉換),是小型別到大型別的轉換。 2.向下型別轉換(強制型別轉換),是大型別到小型別 3.instanceof運算子,來解決引用物件的型別,避免型別轉換的安全性問題 抽象類 1.抽象類前使用abstract關鍵字修飾,

Java方法呼叫引數傳遞探討

有這樣一段程式,看看它會輸出什麼結果 public class Test { public static void main(String [] args){ System.out.println(new B().getVa

深入理解系列之JAVA機制(過載/重寫)

多型(Polymorphism)按字面的意思就是“多種狀態”。在面嚮物件語言中,介面的多種不同的實現方式即為多型(來自百度百科)。所以,按照這個意思其實多型的“主題”是物件,但是實際在我們運用中我們常把“過載”和“重寫”稱之為“多型”其實這是不嚴謹的!過載

Java 的強制型別轉換

目前多型情況下不能訪問子類特有的成員。 如果需要訪問子類特有的成員,那麼需要進行型別強制轉換. 基本資料型別的轉換 &nbs

java的關係使用

在java中規定:一個父類可以有多個子類,但是一個子類只能有一個父類。子類可以通過extends關鍵字來繼承父類。做個比較通俗的比喻,就像一個父親可以有多個親孩子,但是一個孩子只能有一個親生父親。 1.繼承以及重寫:子類繼承父類是對父類屬性和方法的全面繼承,同時子類

Java繼承建構函式的問題

Java子類繼承父類在例項化時預設呼叫的是父類的無參建構函式,不論例項化時呼叫的是子類的有參還是無參建構函式,可以參考這篇Java子類例項化總是呼叫父類的無參構造方法 1、當父類沒有顯式定義構造方法時,編輯器會預設為此類新增一個隱式無參建構函式。此時子類可以有自己的無參和有參構造方法。 2、

Java丟擲異常的處理

  (尊重勞動成果,轉載請註明出處:https://blog.csdn.net/qq_25827845/article/details/85109390冷血之心的部落格)   背景:         這篇部落格的靈感來自

關於java轉型的問題java.lang.ClassCastException

我們都知道,java是面向物件的語言,繼承是其一個很重要的特性,看下面這段程式碼:package my.java.test; class FatherClass { int fatherField; void fatherMethod() { Syst

Java的繼承:的關係

一、父類引用指向子類物件時 1、若子類覆蓋了某方法,則父類引用呼叫子類重新定義的新方法 2、若子類未覆蓋某方法,則父類引用呼叫父類本身的舊方法 3、若子類覆蓋了某屬性,但父類引用仍呼叫父類本身的舊屬性 4、若子類未覆蓋某屬性,則父類引用呼叫父類本身的舊屬性 5、父類引用不

C#之間相互轉換

mage all spa 分享 mic ack 子類 utl round 所用到的類文件:Person.cs:Student.cs:Teacher.cs:問題1:總結:1 父類不能直接強制轉換成子類2 只有父類對象指向子類,那麽父類是可以強制轉換成子類,如果父類對象沒有指向

Java——超物件之間的轉換

繼承是Java中常用的一項特性,通過繼承我們可以省去很多麻煩。 而Java中超類和子類物件之間的轉換則是很多新手的常遇見的難題,要是處理不好,恐怕會因為這個很特殊的問題導致一些潛在的危險,讓你整整一個晚上都在除錯程式以解決一個讓人抓狂的java.lang.ArrayStoreException異

“全棧2019”Java第五十八章:方法返回型別可以是型別

難度 初級 學習時間 10分鐘 適合人群 零基礎 開發語言 Java 開發環境 JDK v11 IntelliJ IDEA v2018.3 文章原文連結 “全棧2019”Java第五十八章:多型中方法返回型別可以是子類型別 下一章 “全棧2019”Java第五十九章:抽

java的繼承以及過載重寫

繼承(inheritance)        簡單的說,繼承就是在一個現有型別的基礎上,通過增加新的方法或者重定義已有方法(下面會講到,這種方式叫重寫)的方式,產生一個新的型別。繼承是面向物件的三個基本特徵--封裝、繼承、多型的其中之一,我們在使用JAVA時編寫的每一個

Java-方法過載

什麼是多型、過載 1. 多型 對多型現象的理解 多型是面向物件的一個重要特徵。關於定義性的概念,相信網上有很多資料,不再多說。這裡說說我自己的理解。多型是指在執行期間,呼叫某個類物件的方法會有不同的行為。舉個最普遍的例子來說: 基類:Shape

3.Java面向物件程式設計OOA/OOP/OOD/OOAD()/UML圖、函數語言程式設計Scala(JVM)---與物件、封裝繼承、構造方法、覆寫/重寫/override

一、緒論 1.面向物件程式設計正規化(C++、Java、Go)------能進行現實生活的抽象。             每個物件都是一個類。類中包含屬性與方法。 OOA:面向物件分析 OOP:面向物件程式設計

【學習筆記】 唐大仕—Java程式設計 第5講 深入理解Java語言之5.2 及虛方法呼叫

/** * 多型及虛方法呼叫 * @author cnRicky * @date 2018.11.7 */ 多型 多型(Polymorphism)是指一個程式中相同的名字表示不同的含義的情況 多型有兩種情形 編譯時多型:  *過載(Overload)(多個同名的不同方法)  *如 p.sayH

java方法引數是基本型別引用型別的區別

方法引數是基本型別時,傳遞的是值。 方法引數是引用型別時,傳遞的是記憶體地址值 當引數是基本型別時,在呼叫方法時將值傳遞到方法中,執行方法,執行結束方法退出,對原本main中定義的變數沒有任何操作(方法中沒有return)。即:此時只跟棧有關係,方法執行完之後(方法中沒有return),會彈棧。

“全棧2019”Java第五十七章:與構造方法詳解

難度 初級 學習時間 10分鐘 適合人群 零基礎 開發語言 Java 開發環境 JDK v11 IntelliJ IDEA v2018.3 文章原文連結 “全棧2019”Java第五十七章:多型與構造方法詳解 下一章 “全棧2019”Java第五十八章:多型中方法返回型