[英]How does inheritance in Java work?
我們有下一堂課:
class Super {
void foo() {
System.out.println("Super");
}
}
class Sub extends Super {
void foo() {
super.foo();
System.out.println("Sub");
}
}
public class Clazz {
public static void main(String[] args) {
new Sub().foo();
}
}
輸出是:
超
子
super
禮物是什么? 它是父類的對象,哪個孩子保持為字段?
我試過谷歌,但我找到的只是關於如何繼承類等的常見信息。
你還在告訴我顯而易見的事情。 也許我的問題有點誤導,但我會試着改寫它:
super
調用方法時,你說,我們正在訪問父方法。 但是如何在沒有父對象的情況下調用此方法呢? super
同this
? 如您所知, this
是對具體對象的引用。 子類不維護任何表示其父級的特殊字段。 你可能正在思考內部類的某些東西,它們確實維護了對它們外部類的引用。 這是一種特殊情況,並不代表超級子類彼此之間的關系。
在內部,JVM維護一個'方法表',將其加載的每個類與該類可用的方法相關聯。 JVM還知道它加載的所有類之間的關系,包括超子關系。
當您調用super
函數時,JVM實際上做了以下幾件事:
invokespecial
) 如果您要檢查Sub
類的類文件,您會看到foo
方法的類似內容:
void foo();
flags:
Code:
stack=2, locals=1, args_size=1
0: aload_0
1: invokespecial #2 // Method Super.foo:()V
4: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
7: ldc #4 // String Sub
9: invokevirtual #5 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
清單中的第1行顯示了調用超類方法的特殊指令。
好的。 我們一行一步地通過您的代碼。
你的'foo'方法中的第一個陳述是
super.foo();
那是對超類foo
方法的顯式調用。 這是:
void foo() {
System.out.println("Super");
}
所以“Super”輸出到控制台,因為你已經用super
關鍵字明確地調用了這個方法。 super
指的是類的父類,以同樣的方式, this
指的是當前類。
接下來是子類中foo
方法的其余部分:
void foo() {
super.foo();
System.out.println("Sub");
}
在super.foo()
之后,是時候轉到下一個語句,輸出“Sub”。
你的程序首先移動到子類'方法而不是超類的原因是因為一個叫做Polymorphism
的原理。 也就是說,子類從超類中獲取一個方法,並改變它的行為。
抽象類
您不能創建Abstract類的實例,不能,但是使用super
關鍵字,您仍然可以訪問超類的功能。
在Java虛擬機的上下文中
那么,當您進行方法調用時,如果它是實例方法,Java虛擬機將在本地類中查找該方法。 如果找不到它,它將移動到超類。 當您使用Polymorphism
原理時,JVM會在子類中找到具有正確簽名的方法,並停止查找。 這就是繼承和Polymorphism
在Java的上下文中以簡單的方式工作的方式。
覆蓋方法時,可以向子類定義添加具有相同方法簽名(方法字段的名稱,編號和類型)的方法。 這就是JVM找到它的方式,這是存儲重寫方法的地方。
super
是一個關鍵字,允許您調用超類中定義的方法實現。 它不是你的子類的一個領域。
如果不是,那么覆蓋的方法在哪里舉行?
我不太清楚你的意思,但是:
由於Sub
擴展了Super
, Sub
類的定義包括對Super
類定義的引用。
回答更新的問題:
當我們用super調用方法時,你說,我們正在進行父方法。 但是如何在沒有父對象的情況下調用此方法呢?
方法只是一個代碼塊,只是我們需要執行的一系列字節碼指令。 當您調用方法時,JVM的任務是根據您提供的方法名稱和參數確定在哪里找到此代碼塊。 通常,正如其他人所說,它將首先查看調用該方法的對象的類的類定義。 當你使用super
,你告訴JVM不要看這里,而是查看父類定義。
因此,您不需要單獨的Super
和Sub
實例,因為Sub
是 Super
( Super
new Sub() instanceof Super
是true
),並且因為JVM知道super
關鍵字意味着它應該查找構成方法的代碼在Super
的類定義中。
這個超級一樣嗎? 如您所知,這是對具體對象的引用。
不,他們不一樣。 this
是對當前對象的引用,而super
不是對對象的引用,而是一個關鍵字,它影響JVM查找定義正在調用的方法的代碼的位置。
當你寫super.foo();
你正在調用超類方法。
class sub的foo方法通過向超類方法添加指令來覆蓋Super的foo方法。
子類.super.foo()中的foo方法覆蓋調用print super,然后調用System.out.println(“Sub”); 顯示Sub。
試試這個繼承
class Super {
Super()
{
System.out.println("1");
}
void foo() {
System.out.println("Super");
}
}
class Sub extends Super {
public Sub() {
// TODO Auto-generated constructor stub
System.out.println("2");
}
void foo() {
super.foo();
System.out.println("Sub");
}
}
只有一個對象同時是Sub,Super和Object。 它具有每個類的所有非靜態字段。 一個類實際上只需要一個代碼副本用於其方法,甚至是非靜態代碼。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.