ava子類父類屬性的覆蓋 部落格分類: Java
class ParentClass { public int i = 10; } public class SubClass extends ParentClass { public int i = 30; public static void main(String[] args) { ParentClass parentClass = new SubClass(); SubClass subClass = new SubClass(); System.out.println(parentClass.i + subClass.i); } } 控制檯的輸出結果是多少呢?20?40?還是60?
變數,或者叫做類的屬性,在繼承的情況下,如果父類和子類存在同名的變數會出現什麼情況呢?這就是這道題要考查的知識點——變數(屬性)的覆蓋。
這個問題雖然簡單,但是情況卻比較複雜。因為我們不僅要考慮變數、靜態變數和常量三種情況,還要考慮private、friendly(即不加訪問修飾符)、protected和public四種訪問許可權下對屬性的不同影響。
我們先從普通變數說起。依照我們的慣例,先來看一段程式碼:
class ParentClass { private String privateField = "父類變數--private"; /* friendly*/String friendlyField = "父類變數--friendly"; protected String protectedField = "父類變數--protected"; public String publicField = "父類變數--public"; // private的變數無法直接訪問,因此我們給他增加了一個訪問方法 public String getPrivateFieldValue() { return privateField; } } publicclass SubClass extends ParentClass { private String privateField = "子類變數--private"; /* friendly */String friendlyField = "子類變數--friendly"; protected String protectedField = "子類變數--protected"; public String publicField = "子類變數--public"; // private的變數無法直接訪問,因此我們給他增加了一個訪問方法 public String getPrivateFieldValue() { return privateField; } public static void main(String[] args) { // 為了便於查閱,我們統一按照private、friendly、protected、public的順序 // 輸出下列三種情況中變數的值 // ParentClass型別,ParentClass物件 ParentClass parentClass = new ParentClass(); System.out.println("ParentClass parentClass = new ParentClass();"); System.out.println(parentClass.getPrivateFieldValue()); System.out.println(parentClass.friendlyField); System.out.println(parentClass.protectedField); System.out.println(parentClass.publicField); System.out.println(); // ParentClass型別,SubClass物件 ParentClass subClass = new SubClass(); System.out.println("ParentClass subClass = new SubClass();"); System.out.println(subClass.getPrivateFieldValue()); System.out.println(subClass.friendlyField); System.out.println(subClass.protectedField); System.out.println(subClass.publicField); System.out.println(); // SubClass型別,SubClass物件 SubClass subClazz = new SubClass(); System.out.println("SubClass subClazz = new SubClass();"); System.out.println(subClazz.getPrivateFieldValue()); System.out.println(subClazz.friendlyField); System.out.println(subClazz.protectedField); System.out.println(subClazz.publicField); } } 這段程式碼的執行結果如下: ParentClass parentClass = new ParentClass(); 父類變數--private 父類變數--friendly 父類變數--protected 父類變數--public ParentClass subClass = new SubClass(); 子類變數--private 父類變數--friendly 父類變數--protected 父類變數--public SubClass subClazz = new SubClass(); 子類變數--private 子類變數--friendly 子類變數--protected 子類變數--public
從上面的結果中可以看出,private的變數與其它三種訪問許可權變數的不同,這是由於方法的重寫(override)而引起的。關於重寫知識的回顧留給以後的章節,這裡我們來看一下其它三種訪問許可權下變數的覆蓋情況。
分析上面的輸出結果就會發現,變數的值取決於我們定義的變數的型別,而不是建立的物件的型別。
在上面的例子中,同名的變數訪問許可權也是相同的,那麼對於名稱相同但是訪問許可權不同的變數,情況又會怎樣呢?事實勝於雄辯,我們繼續來做測試。由於private變數的特殊性,在接下來的實驗中我們都把它排除在外,不予考慮。
由於上面的例子已經說明了,當變數型別是父類(ParentClass)時,不管我們建立的物件是父類(ParentClass)的還是子類(SubClass)的,都不存在屬性覆蓋的問題,因此接下來我們也只考慮變數型別和建立物件都是子類(SubClass)的情況。
class ParentClass { /* friendly */String field = "父類變數"; } public class SubClass extends ParentClass { protected String field = "子類變數"; public static void main(String[] args) { SubClass subClass = new SubClass(); System.out.println(subClass.field); } } 執行結果: 子類變數 Java程式碼 class ParentClass { public String field = "父類變數"; } public class SubClass extends ParentClass { protected String field = "子類變數"; public static void main(String[] args) { SubClass subClass = new SubClass(); System.out.println(subClass.field); } } 執行結果: 子類變數
上面兩段不同的程式碼,輸出結果確是相同的。事實上,我們可以將父類和子類屬性前的訪問修飾符在friendly、protected和public之間任意切換,得到的結果都是相同的。也就是說訪問修飾符並不影響屬性的覆蓋,關於這一點大家可以自行編寫測試程式碼驗證。
對於靜態變數和常量又會怎樣呢?我們繼續來看:
class ParentClass { public static String staticField = "父類靜態變數"; public final String finalField = "父類常量"; public static final String staticFinalField = "父類靜態常量"; } public class SubClass extends ParentClass { public static String staticField = "子類靜態變數"; public final String finalField = "子類常量"; public static final String staticFinalField = "子類靜態常量"; public static void main(String[] args) { SubClass subClass = new SubClass(); System.out.println(SubClass.staticField); System.out.println(subClass.finalField); System.out.println(SubClass.staticFinalField); } } 執行結果如下: 子類靜態變數 子類常量 子類靜態常量
雖然上面的結果中包含“子類靜態變數”和“子類靜態常量”,但這並不表示父類的“靜態變數”和“靜態常量”可以被子類覆蓋,因為它們都是屬於類,而不屬於物件。
上面的例子中,我們一直用物件來對變數(屬性)的覆蓋做測試,如果是基本型別的變數,結果是否會相同呢?答案是肯定的,這裡我們就不再一一舉例說明了。
最後,我們來做個總結。通過以上測試,可以得出一下結論:
由於private變數受訪問許可權的限制,它不能被覆蓋。
屬性的值取父類還是子類並不取決於我們建立物件的型別,而是取決於我們定義的變數的型別。
friendly、protected和public修飾符並不影響屬性的覆蓋。
靜態變數和靜態常量屬於類,不屬於物件,因此它們不能被覆蓋。
常量可以被覆蓋。
對於基本型別和物件,它們適用同樣的覆蓋規律。
最後我們再回到篇首的那道題,我想答案大家都已經知道了,結果是40。
相關推薦
ava子類父類屬性的覆蓋 部落格分類: Java
Java codeclass ParentClass { public int i = 10; } public class SubClass extends ParentClass { public int i = 30;
字串 與 java.sql.Timestamp轉換部落格分類: javaJavaSQL
package test; import java.sql.Timestamp; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; /** * 時間戳與字串轉換 * @auth
C++子類父類成員函式的覆蓋和隱藏例項詳解
https://www.jb51.net/article/117380.htm函式的覆蓋 覆蓋發生的條件:(1) 基類必須是虛擬函式(使用virtual 關鍵字來進行宣告) (2)發生覆蓋的兩個函式分別位於派生類和基類 (3)函式名和引數列表必須完全相同函式的隱藏
java 子類父類相互轉換
col ava ID b- 互轉 執行 bsp extend 子類 子類轉父類 (父類引用指向子類對象) 子類可以轉換為父類,如下父類FruitTest與其子類AppleTest class FruitTest { String str = "FruitTest"
006 子類父類賦值兼容規則
指針 meta namespace vat div cti using fun title 子類和父類的賦值兼容規則 1.同名隱藏(非常重要) 當子類的成員方法(show)和父類的成員方法(show)的名字相同的時候,父類的所有(show)方法,都不能用子類的對象來
子類-父類構造方法調用問題
super 編譯器 創建 得到 沒有 調用父類 com 構造方法 如果 當一個類繼承了某個類時,在子類的構造方法裏,super()必須先被調用;如果你沒有寫,編譯器會自動調用super()方法,即調用了父類的構造方法; 這並不是創建了兩個對象,其實只有一個子類Sub對象;之
子類父類 繼承問題
先看一個題目 輸出結果是啥? 其實這道題考察的是 子類繼承父類 (那些能繼承 和哪些不能繼承 protected 和private 區別)以及子類重寫父類方法; 當在子類中呼叫父類的方法時,其實應該訪問的是父類中熟悉和方法,但是其中的name ,age 以及 read方法被
設計模式 (工廠類=父類;實現類=子類)
設計模式 是在特定環境下人們解決某類重複出現額問題的一套成功的有效的方案 四人組(gang of four) 將"模式"的概念引入軟體工程 “在一定的環境下,用固定套路解決問題” 設計模式的概念 設計模式的基礎是: 多型 設計模式的原則是: 高內聚 ,低耦合(各個類之間少參與,保
Java 子類父類構造方法執行順序
1 public class Test { 2 class Super { 3 int flag = 1; 4 5 Super() { 6 test(); 7 } 8 9 void te
C++子類父類建構函式的關係
構造方法用來初始化類的物件,與父類的其它成員不同,它不能被子類繼承(子類可以繼承父類所有的成員變數和成員方法,但不繼承父類的構造方法)。因此,在建立子類物件時,為了初始化從父類繼承來的資料成員,系統需要呼叫其父類的構造方法。 如果沒有顯式的建構函式,編譯器會給一個預設的建構函式,並且該預設的
java子類父類方法的呼叫
TestParent test = TestParent();test.testA();如果子類重寫了父類的方法,會呼叫子類的方法,若未重寫則呼叫父類的方法。package com.test; /** * @author Administrator * @date 20
java 過載:子類父類 與 多型動態繫結靜態過載
問題: 子類能否過載父類的型別? 答: 完全可以,先看一個例子,接下來會有另一種情況 public class Son extends Father{public void test(int i){System.out.println("This is from Son c
關於集合子類父類關係的全面總結 ,以及遍歷方法的總結 全
集合 集合是個非常好的儲存結構,你補了陣列不能改變長度的不足。可以儲存在臨時記憶體的資料的載體。 集合有兩大父類,分別是Collection 和 Map 1.Collection ——Set——HashSet (不是鍵值
分級聚類——部落格分類 (畫出分級聚類樹狀圖)
《集體智慧程式設計》的第三章——發現組群 下面的測試資料可以在網上下載 通過分級聚類的方式將資料一層一層的聚類,最終聚類為一個大的物件。畫了一個樣例圖如下: 其中將A、B、C、D、E五個物件進行層級聚類,最終的聚類步驟上面已經標出(1,2,3,4)。
部落格處女作:中國剩餘定理與擴充套件中國剩餘定理
各位好啊,這裡是蒟蒻gigo_64的第一篇部落格,,這裡我們開始啦。 本文需要讀者知曉擴充套件歐幾里得,如果不會請點選這個大佬的連結;https://blog.csdn.net/sslz_fsy/article/details/81566257 中國剩餘定理是用來求解一個方程組的。這個方
2018我的部落格歷程:你帶來微笑,我有幸得到
從大學畢業至今已經從事軟體開發2年有餘了,同樣,寫部落格的習慣也已經堅持了2年。我很少寫技術無關的文章,時值年終,我還是想通過分享自己的經歷,同時分享這2年我對 寫部落格的理解,或者說是對 學習方式的思考。 坎坷的博文生涯 堅持寫部落格是一個很有意思的事情,2016年年底之前,我
手把手教你做一個新浪部落格釋出軟體JAVA版本(4)--開啟部落格釋出頁面
前言:很多人用新浪部落格引流,但是以前可以用api釋出,但是現在已經行不通了,市面上也有諸如新浪部落格批量釋出軟體啦,新浪部落格批量發帖啦,新浪部落格釋出軟體啊等等的各種工具,但是小心中槍,一不小心就封號處理了,所以得不償失,於是乎就想自己寫一個
手把手教你做一個新浪部落格釋出軟體JAVA版本(3)--開啟瀏覽器並且登入新浪部落格
在eclipse中新建一個工程(可以自行搜尋怎麼建立,鑑於不是給小白使用者看的,我就不羅嗦怎麼建立了,後面如果有空我補上)。 然後新建一個程式: 注意要把sikuli-script.jar這個包引入到工程裡裡面。 另外還有注意的一個地方,把我們在(手把手教你做一個新浪部落格釋
手把手教你做一個新浪部落格釋出軟體JAVA版本(2)--環境準備
前言:很多人用新浪部落格引流,但是以前可以用api釋出,但是現在已經行不通了,市面上也有諸如新浪部落格批量釋出軟體啦,新浪部落格批量發帖啦,新浪部落格釋出軟體啊等等的各種工具,但是小心中槍,一不小心就封號處理了,所以得不償失,於是
手把手教你做一個新浪部落格釋出軟體JAVA版本(1)--開頭的話
前言:很多人用新浪部落格引流,但是以前可以用api釋出,但是現在已經行不通了,市面上也有諸如新浪部落格批量釋出軟體啦,新浪部落格批量發帖啦,新浪部落格釋出軟體啊等等的各種工具,但是小心中槍,一不小心就封號處理了,所以得不償失,於是乎就想自己寫一個,找來找去,找