繼承是類與類之間的繼承,是一種is a 的關係(繼承的知足條件)函數
繼承的類叫子類 / 派生類,被繼承的叫父類 / 基類優化
Java中的繼承也是單繼承this
經過extends關鍵字來實現繼承關係的spa
class 子類名 extends 父類名 {……}code
class Fu {…} class Sub extends Fu {…}
〈1.優化代碼。減小代碼的重複使用。對象
〈2.複用代碼。子類若是繼承父類,就擁有了父類的方法和屬性,子類能夠複用父類的方法和屬性blog
1.不要爲了繼承而繼承。兩個類必須存在is a 的關係繼承
2.子類不容許繼承父類的構造方法接口
3.子類繼承了父類,在調用本身的構造方法時,若是父類沒有寫有參的構造方法,系統會默認優先調用父類的構造方法內存
若是父類中寫了有參的構造方法,系統就不會調用無參的構造方法,則子類不能調用到父類的構造方法致使報錯
a) 解決辦法:
1. 方案一.在父類中添加無參構造方法讓子類調用
2.方案二.在子類的構造方法裏第一個語句添加super關鍵字及傳入參數
//—>常犯錯題1******************************* class Fu { String name; String color; public Fu(String name, String color) { //1.繼承中不能調用父類的構造方法 this.name = name; this.color = color; } public Fu() { //在父類中添加無參構造方法讓子類調用 } } class Sub extends Fu { int age; public Sub(int age, String name, String color) { super(name,color); // 使用super關鍵字及傳入參數,必須放在第一語句 this.age = age; //this調用本身的構造方法 super();調用父類的構造方法 this.name = name; this.color = color; }
}
4. 若是用private修飾的屬性和方法不能繼承
5. 子類不可以繼承在同一個包
爲何會調用父類的構造方法?
子類在建立對象的時候先初始化父類的變量
在添加變量的時候,不加權限修飾符,默認是friendly修飾,而不是public
訪問權限 |
類 |
包 |
子類 |
其它包 |
public |
∨ |
∨ |
∨ |
∨ |
protect |
∨ |
∨ |
∨ |
× |
default |
∨ |
∨ |
× |
× |
private |
∨ |
× |
× |
× |
指向父類對象的引用空間
super關鍵字:用來初始化父類的屬性和方法
1.當子類和父類的成員變量在重寫同名的時候,能夠經過super來訪問父類的成員變量
2.super能夠調用父類的構造方法
//—>常犯錯題******************************* class Fu { String name = "張三"; String color; public Fu(String name, String color) { this.name = name; this.color = color; } } class Zi extends Fu { int age; public Zi(int age, String name, String color) { super(name,color); this.age = age; } public void run() { //System.out.println(name + "調用了方法"); //默認在name前面隱式性的加了this關鍵字,調用當前本身的成員變量 System.out.println(super.name + "調用了方法"); //****使用super關鍵字,優先調用父類的屬性,而後子類建立的對象,同時給參數賦值會覆蓋父類中name的值,因此調用super仍是李四 } }
1.在子類的構造方法中調用父類的無參構造方法時用super語句,必須放在第一句
二、super只能出如今子類的方法中,經常使用來調用父類的構造方法
三、super和this不可以同時調用構造方法。由於兩個在子類調用時構造方法時,都須要放在第一位,形成衝突
1.對象不同:
this:當前方法的調用對象。
super:表示父類對象的引用空間。
2.條件不一致:
super: 只能在繼承的條件下使用。
this: 沒有限制。
3.調用的構造方法不同:
super :調用父類的構造方法
this : 調用本類構造方法
當父類的方法知足不了子類的實現,這個時候就經過複寫來實現父類的行爲,來保持本身特性
可是int類型必須保持一致
class Animl { public int run() { return 100; } } class Cat extends Animl { // 重寫父類的方法 public int run() { //父類的是返回值int類型,子類中的是double類型,也會報錯:double與int類型不兼容 return 100; } }
6.和方法的重載加以區分:重載時方法名同樣,參數列表的個數、類型或順序不同
7子類的異常類型要小於或等於父類的異常類型
先初始化父類的屬性和方法,而後才初始化子類的屬性和方法
1. 判斷某一個對象是否由這個類建立
2. 使用前提:繼承關係
語法:對象 instanceof 類名;
//在Student類繼承於Person類 class Demo { public static void main(String[] args) { //判斷p對象是否屬於Person類 Person p = new Person(); boolean b1 = p instanceof Person; System.out.println(b1); //true 表示這個對象是這個類建立的 Student s = new Student(); boolean b2 = s instanceof Person; //必須知足繼承Person類 System.out.println(b2); //true 表示這個對象是這個類建立的 } }
final關鍵字做爲修飾符,可理解爲「最終的」意思
class Yuan{ int r; public final static double pi = 3.14; //final修飾的屬性時可直接賦值,並且只能賦值一次 public Yuan(int r) { this.r = r; } public void area() { //final修飾的屬性不能在構造方法中初始化 System.out.println("圓的面積是:" + r*r*pi); } } class Demo{ //常見錯誤點********** public static void main(String[] args) {
final Yuan yu = new Yuan(10); yu.area(); //參數列表中的變量是都是局部變量,因此在兩個方法中的值是互不影響的 test(yu); } public static void test(Yuan you) { you = new Yuan(20); //******建立了一個新的地址,因此能夠改變值,這兒的形參名能夠和上面主函數傳遞進來的參數不同,兩個都是指向的是不一樣一個內存空間 you.area(); } }
final的內存分析圖:
3. 屬性:用final修飾的屬性必須初始化並且只能初始化一次
可在添加屬性直接賦值,在沒有添加static修飾的時候,也可在構造方法或主方法中賦值,可是不能再普通方法中給final初始化
4.變量:變量的值必須賦值一次並且只能賦值一次,賦值事後的變量就變成了常量(常量:不能改變的量)。不論是修飾基本數據類型仍是引用數據類型,第一次的結果爲最終的結果,修改值將會報錯
爲何只能初始化一次?在沒有final修飾的屬性中,即便你沒給它賦值,系統會給它一個隱式的默認值,可是用final修飾的時候,沒有給它初始化的話是沒有值的,全部會報錯
Final修飾常量語法:public final static基本數據類型變量名
public static void main(String[] args) { int a = 10; int b = 20; //定義一個方法交換,基本數據類型之間的賦值,實際是直接把值賦給變量,並無做交換 change(a, b); System.out.println("a = " + a + "," + "b = " + b); //定義一個方法交換,引用數據類型之間的賦值,實際是地址之間的交換來達到目的 int[] arr = {10, 20}; changeArr(arr); System.out.println("a = " + arr[0] + "," + "b = " + arr[1]); } public static void change(int a, int b) { //值沒有交換 int tmp = a; a = b; b = tmp; } public static void changeArr(int[] arr) { //交換了 int tmp = arr[0]; arr[0] = arr[1]; arr[1] = tmp; }
若是形式參數是基本數據類型,傳遞的就是值
若是形式參數是引用類型,傳遞的參數是地址
交換值的內存分析圖
用關鍵字abstract
背景:在重寫父類時,能夠不寫父類的方法,可是有可能會有問題,這就能夠用abstract來強制性讓子類重寫父類的方法
抽象類:一個類若是被abstract修飾那麼這個類就叫抽象類。
1.若是abstract修飾方法,那麼這個方法就叫抽象的方法
2.若是abstract修飾類,那麼這個類叫抽象類。
方法體:方法中大括號的內容就是方法體
abstract class Graphies { int c; int k; abstract public void area(); }
//圓形類 class Roundness extends Graphies { int r; final static double PI = 3.14; //常量的命名規則:首字母大寫,多個單詞用下劃線隔開 public void area() { //必須重寫父類的抽象方法,並且方法名、返回值類型必須相同 System.out.println("這個圓的面積是:" + PI * r * r); } public Roundness(int r) { //PI = 3.14; //若是final修飾的變量加了static修飾,則初始化變量只能在命名的就給它賦值 this.r = r; } } class Demo { public static void main(String[] args) { //建立圓形類調用方法 Roundness r1 = new Roundness(10); r1.area(); } }
1. 用abstract 來修飾的方法不能有方法體。
2.類中有抽象方法,類必須用abstract 來修飾
3.非抽象的類,繼承了這個抽象類,非抽象類中必 須重寫父類全部的抽象方法。
4.抽象類中能夠有非抽象的方法,也能夠沒有
5.抽象類中能夠存在構造方法。-->做用是讓子類能 夠初始化父類中的變量和方法。
6.抽象類不可以建立對象。
緣由:若是建立對象,對象就能夠調用到抽象方法,可是調用的抽象方法沒有意義。
在描述一個事物的時候,發現這個事物確實存在某種行爲,可是這種行爲又不具體,聲明一個沒有實現的行爲,這種行爲就叫抽象的行爲
1.不能和private。
2.不能和static使用。
3.不能和final使用
在Java中很常見
用interface關鍵字來表示接口
結構:interface 接口名();
結構:
class 類 implements 接口名1,接口名2...{
}
一個類若是實現了一個接口,須要將全部的抽象方法實現
1. 用來擴展功能
2. 讓程序解耦
3. 定義約束
// 要繼承的類1 用interface關鍵字 interface Pin { int age = 12; //默認是由final修飾的,必須給它賦值。並且只能賦值一次 public void xie(); //默認是由abstract修飾的 } interface Ca // 要繼承的類2 用interface關鍵字 { public void ca(); } //繼承類 用implements關鍵字 class PinCa implements Pin, Ca //注意繼承多個接口的方法,要用逗號隔開 { public void xie() { System.out.println("寫字的功能"); } public void ca() { System.out.println("擦字的功能"); } } class Demo { public static void main(String[] args) { PinCa pc =new PinCa(); pc.xie(); pc.ca(); }
}
1.接口是一個特殊的類,是能夠定義屬性和方法。
2.成員變量默認是用final修飾的 : public static final 其實是一個常量,必須初始化一次並且只能初始化一次
3.方法都是抽象的: abstract public
4.接口中不能有建立對象、構造方法和普通方法,由於默認是由abstract修飾的類,方法中不能帶有方法體的,不帶主體的普通方法、構造方法是沒有意義的,全部不能使用。
5.接口是給類去實現的,非抽象類實現接口時,必須把接口中的全部方法都實現了。