上圖中,講師類和助教類都繼承員工類,講師類和助教類可以稱為員工類的子類或者派生類,繼承之後,子類可以複用父類別的方法和屬性,子類在實現時只關心自己新增加的成員即可。
//Employee.java
public class Employee {
public void method() {
System.out.println("方法執行!");
}
}
//Teacher.java
//定義了一個員工的子類--講師
public class Teacher extends Employee {
}
//Assistant.java
//定義另一個子類---助教
public class Assistant extends Employee {
}
//主方法
public class Demo01Extends {
public static void main(String[] args) {
Teacher teacher = new Teacher();
teacher.method();
Assistant assistant = new Assistant();
assistant.method();
}
}
注意:
public class Base {
int a;
int b;
}
public class Derived extends Base{
int c;
public void method(){
a = 10; //從父類別繼承
b = 20; //從父類別繼承
c = 30; //存取自己
}
}
public class Base {
int a;
int b;
int c;
}
public class Derived extends Base {
char b; //與父類別同名,不同型別
int c; //與父類別同名,相同型別
public void method(){
a = 10; //存取父類別繼承
b = 20; //存取誰的?
c = 30; //存取誰的?
//d = 40; //編譯器報錯
}
}
注意:
如果存取的成員變數子類中有,則優先存取子類本身的
如果存取的成員變數子類中無,父類別中有,則存取繼承下來的
如果子類與父類別中有同名的成員變數,則優先存取子類自己的,即子類將父類別的同名變數隱藏
成員變數的存取遵循就近原則,自己有就優先存取自己的
public class Base {
public void method1(){
System.out.println("我是父類別方法");
}
}
public class Derived extends Base {
public void method2(){
System.out.println("我是子類方法");
}
public void method(){
method1(); //父類別方法
method2(); //子類方法
}
}
public class Base {
public void method1(){
System.out.println("我是父類別方法");
}
public void method2(){
System.out.println("我是父類別方法");
}
}
public class Derived extends Base {
public void method1(int a){
System.out.println("我是子類方法");
}
public void method2(){
System.out.println("我是子類方法");
}
public void method(){
method1(); //父類別方法
method1(10); //子類方法
method2(); //子類方法
}
}
說明:
通過子類存取成員方法,先看子類本身有沒有,如果有存取自己的,如果沒有,存取父類別的
通過子類存取與父類別同名方法時,如果子類和父類別方法的參數列不同則構成過載,根據呼叫方法傳遞的引數選擇合適的方法存取
如果子類和父類別同名方法的原型一致,則只能存取到子類的
在繼承關係中,方法的名稱不一樣,參數列也一樣。
重寫(override),方法名稱一樣,參數列也一樣,覆蓋,覆寫
過載(overload),方法名稱一樣,參數列不一樣
方法過載是一個類中定義了多個方法名相同,而他們的引數的數量不同或數量相同而型別和次序不同,則稱為方法的過載 (overload)。
方法重寫是在子類存在方法與父類別的方法的名字相同,而且引數的個數與型別一樣,返回值也一樣的方法,就稱為重寫 (override)。
方法過載是一個類的多型性表現,而方法重寫是子類與父類別的一種多型性表現。
方法過載的要求是參數列不同。具體包括以下三種情形。
①引數的數量不同。
②引數的型別不同。
③引數的順序不同。
必須保證父子類之間方法的名稱相同,參數列也相同
@override;寫在方法前面,用來檢測是否是正常的覆蓋重寫
子類方法的返回值必須小於等於父類別的返回值範圍
前提:object類是所有類的最高父類別(祖宗類)
子類方法的許可權必須大於等於父類別的許可權修飾符
public > protected >(default) >private
備註:(default)不是關鍵字default,而是空
super關鍵字用來存取父類別內容,而this關鍵字用來存取本類內容,用法也有三種:
public class Demo01Extends {
public static void main(String[] args) {
ZI zi = new ZI();
zi.Method();
}
}
-----------------------------
public class Fu {
int num = 10;
}
-----------------------------
public class ZI extends Fu {
int num = 20;
public void Method() {
int num = 30;
System.out.println(num);
System.out.println(this.num);//本類的成員變數
System.out.println(super.num);//父類別的成員變數
}
}
構造哪個類的物件,就呼叫哪個類的構造方法,呼叫構造方法時先呼叫基礎類別,在呼叫子類(即在子類中隱藏super() )
public class Base {
public Base(){
System.out.println("Base()");
}
}
public class Derived extends Base {
public Derived(){
System.out.println("Derived()");
}
}
public class Text {
public static void main(String[] args) {
Derived d = new Derived();
}
}
輸出結果:Base()
Derived()
在子類構造方法中,並沒有寫任何關於基礎類別構造的程式碼,但是在構造子類物件時,先執行基礎類別的構造方法,然後執行子類的構造方法
注意:
若父類別顯示定義無參或者預設的構造方法,在子類構造方法的第一行預設有隱含的super呼叫,即呼叫基礎類別的構造方法
如果父類別的構造方法是帶有引數的,此時編譯器不會給子類生成預設的構造方法,此時需要使用者在子類中顯示定義構造方法,並在子類構造方法中選取合適的父類別構造方法呼叫
在子類構造方法中,super(...)呼叫父類別構造時,必須是子類構造方法中的第一條語句
super(...)只能在子類的構造方法中出現一次,並不能和this同時出現
無繼承關係時的執行順序:
public class Person {
String name;
String gender;
int age;
public Person(String name,String gender,int age){
this.name = name;
this.gender = gender;
this.age = age;
System.out.println("我是構造方法");
}
{
System.out.println("我是範例程式碼塊");
}
static {
System.out.println("我是靜態程式碼塊");
}
public static void main(String[] args) {
Person p1 = new Person("xiaoHua","男",12);
System.out.println("=====================");
Person p2 = new Person("xiaoHong","女",15);
}
}
執行結果:
說明:
靜態程式碼塊先執行,且只執行一次,在類載入階段執行
當有物件建立時,才會執行範例程式碼塊,範例程式碼塊執行完後,再執行構造方法
有繼承關係時的執行順序:
public class Person {
String name;
String gender;
int age;
public Person(String name,String gender,int age){
this.name = name;
this.gender = gender;
this.age = age;
System.out.println("person的構造方法");
}
{
System.out.println("person的範例程式碼塊");
}
static {
System.out.println("person的靜態程式碼塊");
}
}
public class Student extends Person{
public Student(String name, String gender, int age) {
super(name, gender, age);
System.out.println("student的構造方法");
}
{
System.out.println("student的範例程式碼塊");
}
static {
System.out.println("student的靜態程式碼塊");
}
}
public class Text {
public static void main(String[] args) {
Student s1 = new Student("張三","男",35);
System.out.println("=====================");
Student s2 = new Student("李四","男",30);
}
}
執行結果:
結論:
父類別靜態程式碼塊優先子類靜態程式碼塊執行,都是最早執行的
父類別範例程式碼塊和父類別構造方法緊接著執行
子類的範例程式碼塊和子類構造方法在接著執行
第二次範例化物件時,父類別和子類的靜態程式碼塊都不會在執行
Java中只支援以下幾種方式:
注意:Java中不支援多支援
final關鍵字可以用來修飾變數,成員方法以及類。
1.修飾變數或欄位,表示常數(即不能修改)
final int a = 10;
a = 20;//編譯報錯
2.修飾類,表示類不能繼承
final public class Person{
}
public class Student extends Person{
}//編譯報錯
3.修飾方法,表示方法不能被重寫(後續在介紹)