標籤:cte 技術分享 ges rac 優先 自己的 提升 方法區 向下轉型
1. 繼承
在Java中的三大特性中存在一種為繼承,繼承究竟是用來解決什麼問題的呢?在我們寫代碼的時候,我們會在一些類中使用相同的屬性和方法,如兩個不同的人(類),共同都有年齡,身高,體重等。
那麼我們就可以把這些相同的屬性和方法提取到一個新的類中,用繼承的方法,讓一個類繼承另一個類,那麼這個類就具有它的屬性和方法了。
class Student{ String name; int age; void study(){ System.out.println("study"); }}
class Worker{ String name; int age; void work(){ System.out.println("work"); }}
具有相同屬性:
String name; int age;
繼承案例:
class Person{ String name; int age;}class Student extends Person{ void study(){ System.out.println("study"); }}class Worker extends Person{ void work(){ System.out.println("work"); }}
利用關鍵字extends,讓類與類之間產生了關係,一個為父類,子類繼承父類,那麼子類就具有父類的屬性和方法了。Java只支援單繼承,不允許多繼承,繼承是為了減少重複代碼,提高代碼的複用性。
在現實世界當中,繼承就是兒子得到老子的東西,在物件導向的世界當中,繼承就是一個類得到了另一個類當中的成員變數和成員方法
在Java中的繼承,其實就是繼承全部屬性和方法(除了構造方法),除了private修飾的變數或者方法,子類無法進行訪問
class Person{String name;int age;Person(){ System.out.prinltn("Person的無參數建構函式");}Person(String name,int age){ this.name=name; this.age=age; System.out.println("Person有參數的建構函式");}void eat(){ System.out.println("定義吃飯的方法");}}
class Student extends Person{//子類繼承父類Student(){ //父類 super(); System.out.println("Student的無參數建構函式");}Student(String name,int age,int id){ super(name,age); this.id=id;}}
在這裡一個子類只能繼承一個父類,一個父類卻可以有很多的子類,如同你只有一個親爸,但你親爸可以有多個兒子一樣。
繼承重點為了提高代碼的複用性,避免方法的調用產生歧義
2. super的使用
使用super調用父類建構函式的方法
例子:
class Person{String name;int age;Person(){ System.out.prinltn("Person的無參數建構函式");}Person(String name,int age){ this.name=name; this.age=age; System.out.println("Person有參數的建構函式");}void eat(){ System.out.println("定義吃飯的方法");}}
class Student extends Person{//子類繼承父類Student(){ //父類 調用父類的無參建構函式 super(); System.out.println("Student的無參數建構函式");}Student(String name,int age,int id){ super(name,age); this.id=id;}}
super()在子類中調用父類對象的引用,通過super()方法調用父類中的方法和屬性,如果沒有在子類寫入super語句,那麼在編譯的時候回自動添加一個super()語句,super()語句必須放在子類構造方法中的第一行,如果父類中只提供了有參的建構函式,那麼就必須手動添加對應的super有參的語句。
super()調用父類,父類對象的引用,代表一個虛擬對象。
3. 方法的重寫,重載
重載的表達
class A{void funA(){ System.out.println("沒有參數的funA函數");}void funA(int i){ System.out.println("有參數的funA函數");}void funA(int i,double d){ System.out.println("擁有兩個參數的funA函數");}}
什麼是複寫(意思和重寫一樣唄)
具有父子關係的兩個類中,父類和子類各有一個函數,這兩個函數的定義(傳回值類型,函數名,參數列表)完全相同
重寫和重載
重載:
方法名一樣,但是參數類型不一樣(不同的參數個數,不同的參數類型,不同的參數次序)
重寫:
子類中定義的某個方法與其父類有相同的名稱和參數,則該方法被重寫了,就是一個方法重寫一遍,一模一樣的,這下記住了吧~
方法的重寫案例:
// 重寫時,注意:子類的方法許可權修飾符要大於等於父類對應的方法的許可權修飾符// 許可權修飾符:public > protected > 預設 > private// 如果父類的方法傳回值類型是參考型別,那麼子類方法的傳回值類型要麼與父類一致,要麼是父類傳回值類型的子類class A {protected void add(){}}class B extends A {protected void add(){}}
4. 多態
多態:是為了提高功能的擴充性,提高複用,為父類的引用指向了子類的對象,多態,多種形態的體現。
多態的體現:
- 編譯時間的體現:方法的重載
- 運行時的體現:向上轉型,方法的重寫
class A{void funA(){ System.out.println("沒有參數的funA函數");}void funA(int i){ System.out.println("有參數的funA函數");}void funA(int i,double d){ System.out.println("擁有兩個參數的funA函數");}}
多態步驟
- 有繼承關係;
- 子類要重寫父類的方法;
- 父類要指向子類的引用
案例
// 抽象動物類abstract class Animal { // 抽象的方法 abstract void eat(); } // 子類繼承父類class Cat extends Animal { // 重寫了父類的方法 public void eat() { System.out.println("吃魚~"); } // 添加了功能 public void work() { System.out.println("抓老鼠~"); } } // 子類繼承了父類class Dog extends Animal { public void eat() { System.out.println("吃骨頭~"); } // 添加了自己的功能 public void work() { System.out.println("看家~"); } }
// 測試類別public class DemoTest { public static void main(String[] args) { // 父類指向子類的對象 // 向上轉型 Animal a = new Cat(); // 調用 Cat 的 eat方法 a.eat(); // 現行判斷 if(a instanceof Cat) { // 向下轉型 Cat c = (Cat)a; // 調用 Cat 的 work 方法 c.work(); } else if(a instanceof Dog) { Dog d = (Dog)a; d.work(); } } }
5. static靜態
被static修飾的變數為靜態變數
被static修飾的方法為靜態方法
靜態變數屬於類而不屬於類的某個執行個體,可被直接類名調用,所以叫類變數
靜態方法屬於類而不屬於類的某個執行個體,可被直接類名調用,所以叫類方法
非靜態成員變數和方法,必須通過執行個體化後通過對象名來調用
靜態方法
class Demo { // 定義一個函數 public void fun1() { System.out.println("Hello"); } // 定義一個靜態函數 public static void fun2() { System.out.println("hello"); }}public class DemoTest { public static void main(String[] args) { // 建立對象 Demo d = new Demo(); d.fun1(); // 對靜態函數進行調用 Demo.fun2(); // 建立對象 Demo d2 = new Demo(); d2.fun2(); }}
靜態修飾的調用方式:1)類名.方法名; 2)對象.方法名
static用來修飾變數,方法,代碼塊,內部類。
靜態變數優先於對象出現,通過類名來調用靜態變數,同樣可以通過對象調用,靜態變數在類載入的時候載入到方法區並賦予預設值。
加入static使用,這個是修飾符,為靜態,被static修飾的為靜態方法,可以直接被類名調用,當然也是可以被對象調用的。
// 定義方法public static void sleep(){ System.out.println("睡覺"); }}class PersonDemo{ public static void main(String[] args){ // 類的調用 Person.sleep(); }}
static修飾成員變數,即為靜態成員變數;修飾方法,為靜態方法,修飾類,為靜態類。靜態方法只能訪問靜態變數,不能訪問非靜態。
static解決了不用建立對象的問題,將方法改為靜態,可讓功能不需要訪問類中定義的成員變數,就不用建立對象來浪費空間了。所以在Java中靜態添加就是為瞭解決這些問題。
在靜態方法中隨著類的載入而載入,隨著類的消失而消失;我們可知靜態方法不能訪問非靜態,可被類名直接調用,而且在靜態方法中不能出現this,super的關鍵字。
靜態方法注意事項:
- 在靜態方法中不能在本類中使用非靜態屬性和非靜態方法
- 靜態方法中可以進行重載,靜態方法也可以被繼承,但不能被重寫(靜態可重載,可繼承,不能被重寫)
對於靜態代碼塊(類只載入一次)
格式:
// 父類靜態 -> 子類靜態 -> 父類非靜態 -> 子類非靜態static {}// 隨著類的載入執行,類只載入一次,靜態代碼塊只執行一次
- 靜態變數 (類變數)
隨著類的載入而載入,並在方法區內進行賦予預設值
- 靜態方法 (類方法)
隨著類的載入而載入,儲存在方法區中,只有被調用的時候才到棧記憶體中執行
- 靜態代碼塊 (用static{ }定義)
6. final修飾符
final用來修飾資料,方法,類
用來修飾資料的為常量,定義好後不能改變,基本類型指定的是實際的值,參考型別指定的是地址。
public static void main(String[] args){ final int i = 3; System.out.println(i);}
重點:
final修飾方法,方法不能被重寫,可重寫,可被繼承
final修飾類,不能被繼承
物件導向,面向過程:面向過程看重過程中的每一步,而物件導向看重的是對象,簡單的事務一般用面向過程,複雜的事務一般建議用物件導向,因為,先有面向過程,才有的物件導向,物件導向是程式員思想的提升,物件導向是基於面向過程的。
類和對象,類是對象的概括,對象則是類的具體表現,如java中的類,不是那麼的具體,而對象就是類的具體的表現了。
在棧的記憶體中儲存的是對象的地址引用,而在堆記憶體中儲存的是實際的對象,對象的賦值實質是傳遞地址值。
this和super必須在構造方法的第一行。
在初始化代碼塊/構造代碼塊中,優先於構造方法執行。
局部代碼塊,用於限制變數的生命週期和提高棧記憶體的利用。
結語
- 下面我將繼續對
Java、 Android中的其他知識 深入講解 ,有興趣可以繼續關注
- 小禮物走一走 or 點贊
Java面試集合(五)