目錄
static
靜態變量及其訪問
實例變量及其訪問
靜態方法及其訪問
實例方法及其訪問
總結
繼承
作用
定義格式
示例
總結
子類不能繼承的內容
繼承后的特點
成員變量
成員變量不重名
?成員變量重名
super訪問父類成員變量
成員方法
成員方法不重名
成員方法重名
方法重寫
@Override重寫注解
構造方法
super(...)和this(...)
super和this的用法格式
this(...)用法演示
繼承的特點
?編輯
static
?static
?關鍵字,可以用來修飾的成員變量和成員方法
被static修飾的成員是屬于類的,放在靜態區中
沒有static修飾的成員變量和方法則是屬于對象的
在類中定義了一些成員變量,例如name,age,sex ,發現創建的每個對象都存在些成員變量(每個對象都可以訪問這些變量),name ,age , sex是每個學生對象都應該有的屬性,應該屬于每個對象。
在Java中,成員(變量和方法)等是存在所屬性的,Java通過static關鍵字來區分。
靜態變量及其訪問
有static修飾成員變量,說明這個成員變量是屬于類的,這個成員變量稱為類變量或者靜態成員變量。 直接用類名訪問即可,因為類只有一個,所以靜態成員變量在內存區域中只存在一份,所有的對象都可以共享這個變量。
定義格式
修飾符 static 數據類型 變量名 = 初始值;
示例
public class Student {public static String schoolName = "123"; // 屬于類,只有一份}
靜態成員變量的訪問
格式:類名.靜態變量
public static void main(String[] args){System.out.println(Student.schoolName); //123Student.schoolName = "111";System.out.println(Student.schoolName); // 111
}
實例變量及其訪問
無static修飾的成員變量屬于每個對象的, 這個成員變量叫實例變量
實例成員變量屬于每個對象,必須創建類的對象才可以訪問。
訪問格式:對象.實例成員變量
靜態方法及其訪問
有static修飾成員方法,說明這個成員方法是屬于類的,這個成員方法稱為類方法或者靜態方法。 直接用類名訪問即可,因為類只有一個,所以靜態方法在內存區域中只存在一份,所有的對象都可以共享這個方法。
與靜態成員變量一樣,靜態方法也是直接通過類名.方法名稱即可訪問。
示例
public class Student{public static String schoolName = "123"; // 屬于類,只有一份public static void study(){System.out.println("我學習"); }
}
靜態成員變量的訪問
格式:類名.靜態方法
public static void main(String[] args){Student.study();
}
實例方法及其訪問
無static修飾的成員方法屬于每個對象的,這個成員方法也叫做實例方法。
實例方法是屬于每個對象,必須創建類的對象才可以訪問。
格式:對象.實例方法
示例:
public class Student {// 實例變量private String name ;// 無 static修飾,實例方法。屬于每個對象,必須創建對象調用public void run(){System.out.println("學生可以跑步");}// 無 static修飾,實例方法public void sleep(){System.out.println("學生睡覺");}public static void study(){}
}
public static void main(String[] args){// 創建對象 Student stu = new Student ;stu.name = "徐干";// Student.sleep();// 報錯,必須用對象訪問。stu.sleep();stu.run();
}
總結
1.當 static
修飾成員變量或者成員方法時,該變量稱為靜態變量,該方法稱為靜態方法。該類的每個對象都共享同一個類的靜態變量和靜態方法。任何對象都可以更改該靜態變量的值或者訪問靜態方法。但是不推薦這種方式去訪問。因為靜態變量或者靜態方法直接通過類名訪問即可,完全沒有必要用對象去訪問。
2.無static修飾的成員變量或者成員方法,稱為實例變量,實例方法,實例變量和實例方法必須創建類的對象,然后通過對象來訪問。
3.static修飾的成員屬于類,會存儲在靜態區,是隨著類的加載而加載的,且只加載一次,所以只有一份,節省內存。存儲于一塊固定的內存區域(靜態區),所以,可以直接被類名調用。它優先于對象存在,所以,可以被所有對象共享。
4.無static修飾的成員,是屬于對象,可以有很多個,對象有多少個,他們就會出現多少份。所以必須由對象調用。
繼承
繼承:就是子類繼承父類的屬性和行為,使得子類對象可以直接具有與父類相同的屬性、相同的行為。子類可以直接訪問父類中的非私有的屬性和行為。
多個類可以稱為子類,單獨被繼承的那一個類稱為父類、超類(superclass)或者基類。
作用
- 提高代碼的復用性(減少代碼冗余,相同代碼重復利用)
- 使類與類之間產生了關系
定義格式
通過 extends
關鍵字,可以聲明一個子類繼承另外一個父類,定義格式如下:
class 父類 {//
}class 子類 extends 父類 {//
}
Java是單繼承的,一個類只能繼承一個直接父類
示例
使用繼承定義以下類:
- 學生類 屬性:姓名,年齡 行為:吃飯,睡覺
- 老師類 屬性:姓名,年齡,薪水 行為:吃飯,睡覺,教書
- 班主任 屬性:姓名,年齡,薪水 行為:吃飯,睡覺,管理
?父類Human類
public class Human {// 合理隱藏private String name ;private int age ;// 合理暴露public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}}
子類Teacher類
public class Teacher extends Human {// 工資private double salary ;// 特有方法public void teach(){System.out.println("老師在認真教技術!");}public double getSalary() {return salary;}public void setSalary(double salary) {this.salary = salary;}
}
子類Student類
public class Student extends Human{}
子類BanZhuren類
public class Teacher extends Human {// 工資private double salary ;// 特有方法public void admin(){System.out.println("班主任強調紀律問題!");}public double getSalary() {return salary;}public void setSalary(double salary) {this.salary = salary;}
}
測試類
public class Test {public static void main(String[] args) {Teacher dlei = new Teacher();dlei.setName("播仔");dlei.setAge("31");dlei.setSalary(1000.99);System.out.println(dlei.getName());System.out.println(dlei.getAge());System.out.println(dlei.getSalary());dlei.teach();BanZhuRen linTao = new BanZhuRen();linTao.setName("靈濤");linTao.setAge("28");linTao.setSalary(1000.99);System.out.println(linTao.getName());System.out.println(linTao.getAge());System.out.println(linTao.getSalary());linTao.admin();Student xugan = new Student();xugan.setName("播仔");xugan.setAge("31");//xugan.setSalary(1000.99); // xugan沒有薪水屬性,報錯!System.out.println(xugan.getName());System.out.println(xugan.getAge());}}
總結
1.繼承實際上是子類相同的屬性和行為可以定義在父類中,子類特有的屬性和行為由自己定義,這樣就實現了相同屬性和行為的重復利用,從而提高了代碼復用。
2.子類繼承父類,就可以直接得到父類的成員變量和方法。
子類不能繼承的內容
并不是父類的所有內容都可以給子類繼承
子類不能繼承父類的構造方法
子類可以繼承父類的私有成員(成員變量,方法),只是子類無法直接訪問而已,可以通過getter/setter方法訪問父類的private成員變量。
public class Demo03 {public static void main(String[] args) {Zi z = new Zi();System.out.println(z.num1);
// System.out.println(z.num2); // 私有的子類無法使用// 通過getter/setter方法訪問父類的private成員變量System.out.println(z.getNum2());z.show1();// z.show2(); // 私有的子類無法使用}
}class Fu {public int num1 = 10;private int num2 = 20;public void show1() {System.out.println("show1");}private void show2() {System.out.println("show2");}public int getNum2() {return num2;}public void setNum2(int num2) {this.num2 = num2;}
}class Zi extends Fu {
}
繼承后的特點
成員變量
成員變量不重名
如果子類父類中出現不重名的成員變量,這時的訪問是沒有影響的。
class Fu {// Fu中的成員變量int num = 5;
}
class Zi extends Fu {// Zi中的成員變量int num2 = 6;// Zi中的成員方法public void show() {// 訪問父類中的numSystem.out.println("Fu num="+num); // 繼承而來,所以直接訪問。// 訪問子類中的num2System.out.println("Zi num2="+num2);}
}
class Demo04 {public static void main(String[] args) {// 創建子類對象Zi z = new Zi(); // 調用子類中的show方法z.show();
//Fu num = 5
//Zi num2 = 6}
}
?成員變量重名
如果子類父類中出現重名的成員變量,這時的訪問是有影響的。
class Fu1 {// Fu中的成員變量。int num = 5;
}
class Zi1 extends Fu1 {// Zi中的成員變量int num = 6;public void show() {// 訪問父類中的numSystem.out.println("Fu num=" + num);// 訪問子類中的numSystem.out.println("Zi num=" + num);}
}
class Demo04 {public static void main(String[] args) {// 創建子類對象Zi1 z = new Zi1(); // 調用子類中的show方法z1.show();
//Fu num = 6
//Zi num = 6}
}
子父類中出現了同名的成員變量時,子類會優先訪問自己對象中的成員變量。如果此時想訪問父類成員變量可以使用super關鍵字。
super訪問父類成員變量
子父類中出現了同名的成員變量時,在子類中需要訪問父類中非私有成員變量時,需要使用super
關鍵字,修飾父類成員變量,類似于?this
。
super代表的是父類對象的引用
this代表的是當前對象的引用。
使用格式:
super.父類成員變量名
子類方法需要修改,代碼如下:
class Fu {// Fu中的成員變量。int num = 5;
}class Zi extends Fu {// Zi中的成員變量int num = 6;public void show() {int num = 1;// 訪問方法中的numSystem.out.println("method num=" + num);// 訪問子類中的numSystem.out.println("Zi num=" + this.num);// 訪問父類中的numSystem.out.println("Fu num=" + super.num);}
}class Demo04 {public static void main(String[] args) {// 創建子類對象Zi1 z = new Zi1(); // 調用子類中的show方法z1.show(); }
}演示結果:
method num=1
Zi num=6
Fu num=5
如果Fu 類中的成員變量是非私有的,子類中可以直接訪問
如果Fu 類中的成員變量是私有的,子類是不能直接訪問的
父類中使用private修飾成員變量,可以在父類中提供公共的getXxx方法和setXxx方法訪問父類的私有成員變量
成員方法
成員方法不重名
如果子類父類中出現不重名的成員方法,這時的調用是沒有影響的。對象調用方法時,會先在子類中查找有沒有對應的方法,若子類中存在就會執行子類中的方法,若子類中不存在就會執行父類中相應的方法。
class Fu {public void show() {System.out.println("Fu類中的show方法執行");}
}
class Zi extends Fu {public void show2() {System.out.println("Zi類中的show2方法執行");}
}
public class Demo05 {public static void main(String[] args) {Zi z = new Zi();//子類中沒有show方法,但是可以找到父類方法去執行z.show(); z.show2();}
}
成員方法重名
如果子類父類中出現重名的成員方法,創建子類對象,子類對象調用該方法時,子類對象會優先調用自己的方法。
class Fu {public void show() {System.out.println("Fu show");}
}
class Zi extends Fu {//子類重寫了父類的show方法public void show() {System.out.println("Zi show");}
}
public class ExtendsDemo05{public static void main(String[] args) {Zi z = new Zi();// 子類中有show方法,只執行重寫后的show方法z.show(); // Zi show}
}
方法重寫
方法重寫 :子類中出現與父類一模一樣的方法時(返回值類型,方法名和參數列表都相同),會出現覆蓋效果,也稱為重寫或者復寫。聲明不變,重新實現。
發生在子父類之間的關系。 子類繼承了父類的方法,但是子類覺得父類的這方法不足以滿足自己的需求,子類重新寫了一個與父類同名的方法,以便覆蓋父類的該方 法。
例如:定義了一個動物類代碼如下:
public class Animal {public void run(){System.out.println("動物跑的很快!");}public void cry(){System.out.println("動物都可以叫~~~");}
}
然后定義一個貓類,貓可能認為父類cry()方法不能滿足自己的需求
代碼如下:
public class Cat extends Animal {public void cry(){System.out.println("我們一起學貓叫,喵喵喵!喵的非常好聽!");}
}public class Test {public static void main(String[] args) {// 創建子類對象Cat ddm = new Cat();// 調用父類繼承而來的方法ddm.run();// 調用子類重寫的方法ddm.cry();}
}
@Override重寫注解
-
@Override:注解,重寫注解校驗!
-
這個注解標記的方法,就說明這個方法必須是重寫父類的方法,否則編譯階段報錯。
-
建議重寫都加上這個注解,一方面可以提高代碼的可讀性,一方面可以防止重寫出錯!
加上后的子類代碼形式如下:
public class Cat extends Animal {// 聲明不變,重新實現// 方法名稱與父類全部一樣,只是方法體中的功能重寫了!@Overridepublic void cry(){System.out.println("我們一起學貓叫,喵喵喵!喵的非常好聽!");}
}
方法重寫是發生在子父類之間的關系
子類方法覆蓋父類方法,必須要保證權限大于等于父類權限
子類方法覆蓋父類方法,返回值類型、函數名和參數列表都要一模一樣
構造方法
構造方法的定義格式和作用
-
構造方法的名字是與類名一致的,所以子類是無法繼承父類構造方法
-
構造方法的作用是初始化對象成員變量數據。所以子類的初始化過程中,必須先執行父類的初始化動作。子類的構造方法中默認有一個
super()
,表示調用父類的構造方法,父類成員變量初始化后,才可以給子類使用。(先有爸爸,才能有兒子)
繼承后子類構方法器特點:子類所有構造方法的第一行都會默認先調用父類的無參構造方法
按如下需求定義類:
1. 人類
? ?成員變量: 姓名,年齡
? ?成員方法: 吃飯
2. 學生類
? ?成員變量: 姓名,年齡,成績
? ?成員方法: 吃飯
代碼如下:
class Person {private String name;private int age;public Person() {System.out.println("父類無參");}// getter/setter省略
}class Student extends Person {private double score;public Student() {//super(); // 調用父類無參,默認就存在,可以不寫,必須再第一行System.out.println("子類無參");}public Student(double score) {//super(); // 調用父類無參,默認就存在,可以不寫,必須再第一行this.score = score; System.out.println("子類有參");}}public class Demo07 {public static void main(String[] args) {Student s1 = new Student();System.out.println("----------");Student s2 = new Student(99.9);}
}輸出結果:
父類無參
子類無參
----------
父類無參
子類有參
子類構造方法執行的時候,都會在第一行默認先調用父類無參數構造方法一次。
子類構造方法的第一行都隱含了一個super()去調用父類無參數構造方法,super()可以省略不寫。
super(...)和this(...)
子類有參數構造方法只是初始化了自己對象中的成員變量score,而父類中的成員變量name和age依然是沒有數據的,怎么解決這個問題呢,可以借助與super(...)調用父類構造方法,以便初始化繼承自父類對象的name和age.
super和this的用法格式
super和this完整的用法如下
this.成員變量 ? ??? ?-- ? ?本類的
super.成員變量 ? ??? ?-- ? ?父類的this.成員方法名() ??? ?-- ? ?本類的 ? ?
super.成員方法名() ? -- ? ?父類的
調用構造方法格式:
super(...) -- 調用父類的構造方法,根據參數匹配確認
this(...) -- 調用本類的其他構造方法,根據參數匹配確認
super(....)用法演示
class Person {private String name ="鳳姐";private int age = 20;public Person() {System.out.println("父類無參");}public Person(String name , int age){this.name = name ;this.age = age ;}// getter/setter省略
}class Student extends Person {private double score = 100;public Student() {//super(); // 調用父類無參構造方法,默認就存在,可以不寫,必須再第一行System.out.println("子類無參");}public Student(String name , int age,double score) {super(name ,age);
// 調用父類有參構造方法Person(String name , int age)初始化name和agethis.score = score; System.out.println("子類有參");}// getter/setter省略
}public class Demo07 {public static void main(String[] args) {// 調用子類有參數構造方法Student s2 = new Student("張三",20,99);System.out.println(s2.getScore()); // 99System.out.println(s2.getName()); // 輸出 張三System.out.println(s2.getAge()); // 輸出 20}
}
子類的每個構造方法中均有默認的super(),調用父類的空參構造。手動調用父類構造會覆蓋默認的super()
super() 和 this() 都必須是在構造方法的第一行,所以不能同時出現
super(..)是根據參數去確定調用父類哪個構造方法的
super(...)案例圖解
父類空間優先于子類對象產生
在每次創建子類對象時,先初始化父類空間,再創建其子類對象本身。
先初始化父類,無論是否為私有
目的在于子類對象中包含了其對應的父類空間,便可以包含其父類的成員,如果父類成員非private修飾,則子類可以隨意使用父類成員。代碼體現在子類的構造調用時,一定先調用父類的構造方法。理解圖解如下:
this(...)用法演示
this(...)
默認是去找本類中的其他構造方法,根據參數來確定具體調用哪一個構造方法。
為了借用其他構造方法的功能。
package com.itheima._08this和super調用構造方法;
/*** this(...):* 默認是去找本類中的其他構造方法,根據參數來確定具體調用哪一個構造方法。* 為了借用其他構造方法的功能。**/
public class ThisDemo01 {public static void main(String[] args) {Student xuGan = new Student();System.out.println(xuGan.getName()); // 輸出:徐干System.out.println(xuGan.getAge());// 輸出:21System.out.println(xuGan.getSex());// 輸出: 男}
}class Student{private String name ;private int age ;private char sex ;public Student() {// 很弱,我的兄弟很牛逼啊
//我可以調用其他構造方法:Student(String name, int age, char sex)this("徐干",21,'男');}public Student(String name, int age, char sex) {this.name = name ;this.age = age ;this.sex = sex ;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public char getSex() {return sex;}public void setSex(char sex) {this.sex = sex;}
}
子類的每個構造方法中均有默認的super(),調用父類的空參構造。手動調用父類構造會覆蓋默認的super()。
super() 和 this() 都必須是在構造方法的第一行,所以不能同時出現。
super(..)和this(...)是根據參數去確定調用父類哪個構造方法的。
super(..)可以調用父類構造方法初始化繼承自父類的成員變量的數據。
this(..)可以調用本類中的其他構造方法。
繼承的特點
1.Java只支持單繼承,不支持多繼承
// 一個類只能有一個父類,不可以有多個父類。
class A {}
class B {}
class C1 extends A {} // ok
// class C2 extends A, B {} // error
?2.一個類可以有多個子類
// A可以有多個子類
class A {}
class C1 extends A {}
class C2 extends A {}
?3.可以多層繼承
class A {}
class C1 extends A {}
class D extends C1 {}
頂層父類是Object類。所有的類默認繼承Object,作為父類。
會寫一個繼承結構下的標準Javabean即可
需求:
貓:屬性,姓名,年齡,顏色
狗:屬性,姓名,年齡,顏色,吼叫
分享書寫技巧:
1.在大腦中要區分誰是父,誰是子
2.把共性寫到父類中,獨有的東西寫在子類中
3.開始編寫標準Javabean(從上往下寫)
4.在測試類中,創建對象并賦值調用
代碼示例:
package com.itheima.test4;public class Animal {//姓名,年齡,顏色private String name;private int age;private String color;public Animal() {}public Animal(String name, int age, String color) {this.name = name;this.age = age;this.color = color;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getColor() {return color;}public void setColor(String color) {this.color = color;}
}public class Cat extends Animal{//因為貓類中沒有獨有的屬性。//所以此時不需要寫私有的成員變量//空參public Cat() {}//需要帶子類和父類中所有的屬性public Cat(String name, int age, String color) {super(name,age,color);}
}public class Dog extends Animal{//Dog :吼叫private String wang;//構造public Dog() {}//帶參構造:帶子類加父類所有的屬性public Dog(String name, int age, String color,String wang) {//共性的屬性交給父類賦值super(name,age,color);//獨有的屬性自己賦值this.wang = wang;}public String getWang() {return wang;}public void setWang(String wang) {this.wang = wang;}
}public class Demo {public static void main(String[] args) {//Animal : 姓名,年齡,顏色//Cat ://Dog :吼叫//創建狗的對象Dog d = new Dog("旺財",2,"黑色","嗷嗚~~");System.out.println(d.getName()+", " + d.getAge() + ", " + d.getColor() + ", " + d.getWang());//創建貓的對象Cat c = new Cat("中華田園貓",3,"黃色");System.out.println(c.getName() + ", " + c.getAge() + ", " + c.getColor());}
}