新手初學Java繼承、封裝與多態(tài)
面向?qū)ο蟮娜蠛诵奶匦?/h2>
面向?qū)ο箝_發(fā)模式更有利于人們開拓思維,在具體的開發(fā)過程中便于程序的劃分,方便程序員分工合作,提高開發(fā)效率。面向?qū)ο蟪绦蛟O(shè)計有以下優(yōu)點。
- 可重用性:代碼重復使用,減少代碼量,提高開發(fā)效率。下面介紹的面向?qū)ο蟮娜蠛诵奶匦裕ɡ^承、封裝和多態(tài))都圍繞這個核心。
- 可擴展性:指新的功能可以很容易地加入到系統(tǒng)中來,便于軟件的修改。
- 可管理性:能夠?qū)⒐δ芘c數(shù)據(jù)結(jié)合,方便管理。
該開發(fā)模式之所以使程序設(shè)計更加完善和強大,主要是因為面向?qū)ο缶哂欣^承、封裝和多態(tài) 3 個核心特性。
封裝
封裝將類的某些信息隱藏在類內(nèi)部,不允許外部程序直接訪問,只能通過該類提供的方法來實現(xiàn)對隱藏信息的操作和訪問。例如:一臺計算機內(nèi)部極其復雜,有主板、CPU、硬盤和內(nèi)存, 而一般用戶不需要了解它的內(nèi)部細節(jié),不需要知道主板的型號、CPU 主頻、硬盤和內(nèi)存的大小,于是計算機制造商將用機箱把計算機封裝起來,對外提供了一些接口,如鼠標、鍵盤和顯示器等,這樣當用戶使用計算機就非常方便。
封裝的特點:
- 只能通過規(guī)定的方法訪問數(shù)據(jù)。
- 隱藏類的實例細節(jié),方便修改和實現(xiàn)。
實現(xiàn)封裝的具體步驟如下:
- 修改屬性的可見性來限制對屬性的訪問,一般設(shè)為
private
。 - 為每個屬性創(chuàng)建一對賦值(
setter
)方法和取值(getter
)方法,一般設(shè)為 public,用于屬性的讀寫。 - 在賦值和取值方法中,加入屬性控制語句(對屬性值的合法性進行判斷)。
下面以一個員工類的封裝為例介紹封裝過程。一個員工的主要屬性有姓名、年齡、聯(lián)系電話和家庭住址。假設(shè)員工類為 Employee
,示例如下:
public class Employee { private String name; // 姓名 private int age; // 年齡 private String phone; // 聯(lián)系電話 private String address; // 家庭住址 public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { // 對年齡進行限制 if (age < 18 || age > 40) { System.out.println("年齡必須在18到40之間!"); this.age = 20; // 默認年齡 } else { this.age = age; } } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } }
繼承
繼承是面向?qū)ο蟮娜筇卣髦弧@^承和現(xiàn)實生活中的“繼承”的相似之處是保留一些父輩的特性,從而減少代碼冗余,提高程序運行效率。
Java 中的繼承就是在已經(jīng)存在類的基礎(chǔ)上進行擴展,從而產(chǎn)生新的類。已經(jīng)存在的類稱為父類、基類或超類,而新產(chǎn)生的類稱為子類或派生類。在子類中,不僅包含父類的屬性和方法,還可以增加新的屬性和方法。
創(chuàng)建人類 People,并定義 name、age、sex、sn 屬性,代碼如下:
public class People { public String name; // 姓名 public int age; // 年齡 public String sex; // 性別 public String sn; // 身份證號 public People(String name, int age, String sex, String sn) { this.name = name; this.age = age; this.sex = sex; this.sn = sn; } public String toString() { return "姓名:" + name + "\n年齡:" + age + "\n性別:" + sex + "\n身份證號:" + sn; } }
創(chuàng)建 People 類的子類 Student 類,并定義 stuNo 和 department 屬性,代碼如下:
public class Student extends People { private String stuNo; // 學號 private String department; // 所學專業(yè) public Student(String name, int age, String sex, String sn, String stuno, String department) { super(name, age, sex, sn); // 調(diào)用父類中的構(gòu)造方法 this.stuNo = stuno; this.department = department; } public String toString() { return "姓名:" + name + "\n年齡:" + age + "\n性別:" + sex + "\n身份證號:" + sn + "\n學號:" + stuNo + "\n所學專業(yè):" + department; } }
由于 Student 類繼承自 People 類,因此,在 Student 類中同樣具有 People 類的屬性和方法,這里重寫了父類中的 toString() 方法。
注意:如果在父類中存在有參的構(gòu)造方法而并沒有重載無參的構(gòu)造方法,那么在子類中必須含有有參的構(gòu)造方法,因為如果在子類中不含有構(gòu)造方法,默認會調(diào)用父類中無參的構(gòu)造方法,而在父類中并沒有無參的構(gòu)造方法,因此會出錯。
單繼承
Java 語言摒棄了 C++ 中難以理解的多繼承特征,即 Java 不支持多繼承,只允許一個類直接繼承另一個類,即子類只能有一個直接父類,extends 關(guān)鍵字后面只能有一個類名。
很多地方在介紹 Java 的單繼承時,可能會說 Java 類只能有一個父類,嚴格來講,這種說法是錯誤的,應該是一個類只能有一個直接父類,但是它可以有多個間接的父類。
繼承的優(yōu)缺點
在面向?qū)ο笳Z言中,繼承是必不可少的、非常優(yōu)秀的語言機制,它有如下優(yōu)點:
- 實現(xiàn)代碼共享,減少創(chuàng)建類的工作量,使子類可以擁有父類的方法和屬性。
- 提高代碼維護性和可重用性。
- 提高代碼的可擴展性,更好的實現(xiàn)父類的方法。
自然界的所有事物都是優(yōu)點和缺點并存的,繼承的缺點如下:
- 繼承是侵入性的。只要繼承,就必須擁有父類的屬性和方法。
- 降低代碼靈活性。子類擁有父類的屬性和方法后多了些約束。
- 增強代碼耦合性(開發(fā)項目的原則為高內(nèi)聚低耦合)。當父類的常量、變量和方法被修改時,需要考慮子類的修改,有可能會導致大段的代碼需要重構(gòu)。
super關(guān)鍵字
由于子類不能繼承父類的構(gòu)造方法,因此,如果要調(diào)用父類的構(gòu)造方法,可以使用 super 關(guān)鍵字。super 可以用來訪問父類的構(gòu)造方法、普通方法和屬性。
super 關(guān)鍵字的功能:
- 在子類的構(gòu)造方法中顯式的調(diào)用父類構(gòu)造方法
- 訪問父類的成員方法和變量。
super調(diào)用父類構(gòu)造方法
super 關(guān)鍵字可以在子類的構(gòu)造方法中顯式地調(diào)用父類的構(gòu)造方法,基本格式如下:
super(parameter-list);
其中,parameter-list 指定了父類構(gòu)造方法中的所有參數(shù)。super( ) 必須是在子類構(gòu)造方法的方法體的第一行。
聲明父類 Person,類中定義兩個構(gòu)造方法。示例代碼如下:
public class Person { public Person(String name, int age) { } public Person(String name, int age, String sex) { } }
子類 Student 繼承了 Person 類,使用 super 語句來定義 Student 類的構(gòu)造方法。示例代碼如下:
public class Student extends Person { public Student(String name, int age, String birth) { super(name, age); // 調(diào)用父類中含有2個參數(shù)的構(gòu)造方法 } public Student(String name, int age, String sex, String birth) { super(name, age, sex); // 調(diào)用父類中含有3個參數(shù)的構(gòu)造方法 } }
從上述 Student 類構(gòu)造方法代碼可以看出,super 可以用來直接調(diào)用父類中的構(gòu)造方法,使編寫代碼也更加簡潔方便。
編譯器會自動在子類構(gòu)造方法的第一句加上super();
來調(diào)用父類的無參構(gòu)造方法,必須寫在子類構(gòu)造方法的第一句,也可以省略不寫。通過 super 來調(diào)用父類其它構(gòu)造方法時,只需要把相應的參數(shù)傳過去。
super訪問父類成員
當子類的成員變量或方法與父類同名時,可以使用 super 關(guān)鍵字來訪問。如果子類重寫了父類的某一個方法,即子類和父類有相同的方法定義,但是有不同的方法體,此時,我們可以通過 super 來調(diào)用父類里面的這個方法。
使用 super 訪問父類中的成員與 this 關(guān)鍵字的使用相似,只不過它引用的是子類的父類,語法格式如下:
super.member
其中,member 是父類中的屬性或方法。使用 super 訪問父類的屬性和方法時不用位于第一行。
- super調(diào)用成員屬性
當父類和子類具有相同的數(shù)據(jù)成員時,JVM 可能會模糊不清。我們可以使用以下代碼片段更清楚地理解它。
class Person { int age = 12; } class Student extends Person { int age = 18; void display() { System.out.println("學生年齡:" + super.age); } } class Test { public static void main(String[] args) { Student stu = new Student(); stu.display(); } }
輸出結(jié)果為:
學生年齡:12
在上面的例子中,父類和子類都有一個成員變量 age。我們可以使用 super 關(guān)鍵字訪問 Person 類中的 age 變量。
- super調(diào)用成員方法
當父類和子類都具有相同的方法名時,可以使用 super 關(guān)鍵字訪問父類的方法。具體如下代碼所示。
class Person { void message() { System.out.println("This is person class"); } } class Student extends Person { void message() { System.out.println("This is student class"); } void display() { message(); super.message(); } } class Test { public static void main(String args[]) { Student s = new Student(); s.display(); } }
輸出結(jié)果為:
This is student class
This is person class
在上面的例子中,可以看到如果只調(diào)用方法 message( ),是當前的類 message( ) 被調(diào)用,使用 super 關(guān)鍵字時,是父類的 message( ) 被調(diào)用
super和this的區(qū)別
this 指的是當前對象的引用,super 是當前對象的父對象的引用。下面先簡單介紹一下 super 和 this 關(guān)鍵字的用法。
super 關(guān)鍵字的用法:
- super.父類屬性名:調(diào)用父類中的屬性
- super.父類方法名:調(diào)用父類中的方法
- super():調(diào)用父類的無參構(gòu)造方法
- super(參數(shù)):調(diào)用父類的有參構(gòu)造方法
如果構(gòu)造方法的第一行代碼不是 this() 和 super(),則系統(tǒng)會默認添加 super()。
this 關(guān)鍵字的用法:
- this.屬性名:表示當前對象的屬性
- this.方法名(參數(shù)):表示調(diào)用當前對象的方法
當局部變量和成員變量發(fā)生沖突時,使用this.
進行區(qū)分。
關(guān)于 Java super 和 this 關(guān)鍵字的異同,可簡單總結(jié)為以下幾條。
- 子類和父類中變量或方法名稱相同時,用 super 關(guān)鍵字來訪問??梢岳斫鉃?super 是指向自己父類對象的一個指針。在子類中調(diào)用父類的構(gòu)造方法。
- this 是自身的一個對象,代表對象本身,可以理解為 this 是指向?qū)ο蟊旧淼囊粋€指針。在同一個類中調(diào)用其它方法。
- this 和 super 不能同時出現(xiàn)在一個構(gòu)造方法里面,因為 this 必然會調(diào)用其它的構(gòu)造方法,其它的構(gòu)造方法中肯定會有 super 語句的存在,所以在同一個構(gòu)造方法里面有相同的語句,就失去了語句的意義,編譯器也不會通過。
- this( ) 和 super( ) 都指的是對象,所以,均不可以在 static 環(huán)境中使用,包括 static 變量、static 方法和 static 語句塊。
- 從本質(zhì)上講,this 是一個指向?qū)ο蟊旧淼闹羔? 然而 super 是一個 Java 關(guān)鍵字。
多態(tài)
多態(tài)性是面向?qū)ο缶幊痰挠忠粋€重要特征,它是指在父類中定義的屬性和方法被子類繼承之后,可以具有不同的數(shù)據(jù)類型或表現(xiàn)出不同的行為,這使得同一個屬性或方法在父類及其各個子類中具有不同的含義。
對面向?qū)ο髞碚f,多態(tài)分為編譯時多態(tài)和運行時多態(tài)。其中編譯時多態(tài)是靜態(tài)的,主要是指方法的重載,它是根據(jù)參數(shù)列表的不同來區(qū)分不同的方法。通過編譯之后會變成兩個不同的方法,在運行時談不上多態(tài)。而運行時多態(tài)是動態(tài)的,它是通過動態(tài)綁定來實現(xiàn)的,也就是大家通常所說的多態(tài)性。
Java 實現(xiàn)多態(tài)有 3 個必要條件:繼承、重寫和向上轉(zhuǎn)型。只有滿足這 3 個條件,開發(fā)人員才能夠在同一個繼承結(jié)構(gòu)中使用統(tǒng)一的邏輯實現(xiàn)代碼處理不同的對象,從而執(zhí)行不同的行為。
- 繼承:在多態(tài)中必須存在有繼承關(guān)系的子類和父類。
- 重寫:子類對父類中某些方法進行重新定義,在調(diào)用這些方法時就會調(diào)用子類的方法。
- 向上轉(zhuǎn)型:在多態(tài)中需要將子類的引用賦給父類對象,只有這樣該引用才既能可以調(diào)用父類的方法,又能調(diào)用子類的方法。
創(chuàng)建 Figure 類,在該類中首先定義存儲二維對象的尺寸,然后定義有兩個參數(shù)的構(gòu)造方法,最后添加 area() 方法,該方法計算對象的面積。代碼如下:
public class Figure { double dim1; double dim2; Figure(double d1, double d2) { // 有參的構(gòu)造方法 this.dim1 = d1; this.dim2 = d2; } double area() { // 用于計算對象的面積 System.out.println("父類中計算對象面積的方法,沒有實際意義,需要在子類中重寫。"); return 0; } }
創(chuàng)建繼承自 Figure 類的 Rectangle 子類,該類調(diào)用父類的構(gòu)造方法,并且重寫父類中的 area() 方法。代碼如下:
public class Rectangle extends Figure { Rectangle(double d1, double d2) { super(d1, d2); } double area() { System.out.println("長方形的面積:"); return super.dim1 * super.dim2; } }
創(chuàng)建繼承自 Figure 類的 Triangle 子類,該類與 Rectangle 相似。代碼如下:
public class Triangle extends Figure { Triangle(double d1, double d2) { super(d1, d2); } double area() { System.out.println("三角形的面積:"); return super.dim1 * super.dim2 / 2; } }
創(chuàng)建 Test 測試類,在該類的 main() 方法中首先聲明 Figure 類的變量 figure,然后分別為 figure 變量指定不同的對象,并調(diào)用這些對象的 area() 方法。代碼如下:
public class Test { public static void main(String[] args) { Figure figure; // 聲明Figure類的變量 figure = new Rectangle(9, 9); System.out.println(figure.area()); System.out.println("==============================="); figure = new Triangle(6, 8); System.out.println(figure.area()); System.out.println("==============================="); figure = new Figure(10, 10); System.out.println(figure.area()); } }
從上述代碼可以發(fā)現(xiàn),無論 figure 變量的對象是 Rectangle 還是 Triangle,它們都是 Figure 類的子類,因此可以向上轉(zhuǎn)型為該類,從而實現(xiàn)多態(tài)。
執(zhí)行上述代碼,輸出結(jié)果如下:
長方形的面積:
81.0 ===============================
三角形的面積:
24.0 ===============================
父類中計算對象面積的方法,沒有實際意義,需要在子類中重寫。
0.0
instanceof關(guān)鍵字
嚴格來說 instanceof 是 Java 中的一個雙目運算符,由于它是由字母組成的,所以也是 Java 的保留關(guān)鍵字。在 Java 中可以使用 instanceof 關(guān)鍵字判斷一個對象是否為一個類(或接口、抽象類、父類)的實例,語法格式如下所示。
boolean result = obj instanceof Class
其中,obj 是一個對象,Class 表示一個類或接口。obj 是 class 類(或接口)的實例或者子類實例時,結(jié)果 result 返回 true,否則返回 false。
下面介紹 Java instanceof 關(guān)鍵字的幾種用法。
1)聲明一個 class 類的對象,判斷 obj 是否為 class 類的實例對象(很普遍的一種用法),如以下代碼:
Integer integer = new Integer(1); System.out.println(integer instanceof Integer); // true
2)聲明一個 class 接口實現(xiàn)類的對象 obj,判斷 obj 是否為 class 接口實現(xiàn)類的實例對象,如以下代碼:
Java 集合中的 List 接口有個典型實現(xiàn)類 ArrayList。
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable
所以我們可以用 instanceof 運算符判斷 ArrayList 類的對象是否屬于 List 接口的實例,如果是返回 true,否則返回 false。
ArrayList arrayList = new ArrayList(); System.out.println(arrayList instanceof List); // true
或者反過來也是返回 true
List list = new ArrayList(); System.out.println(list instanceof ArrayList); // true
3)obj 是 class 類的直接或間接子類
我們新建一個父類 Person.class,代碼如下:
public class Person { }
創(chuàng)建 Person 的子類 Man,代碼如下:
public class Man extends Person { }
測試代碼如下:
Person p1 = new Person(); Person p2 = new Man(); Man m1 = new Man(); System.out.println(p1 instanceof Man); // false System.out.println(p2 instanceof Man); // true System.out.println(m1 instanceof Man); // true
第 4 行代碼中,Man 是 Person 的子類,Person 不是 Man 的子類,所以返回結(jié)果為 false。
值得注意的是 obj 必須為引用類型,不能是基本類型。例如以下代碼:
int i = 0; System.out.println(i instanceof Integer); // 編譯不通過 System.out.println(i instanceof Object); // 編譯不通過
所以,instanceof 運算符只能用作對象的判斷。
當 obj 為 null 時,直接返回 false,因為 null 沒有引用任何對象。
Integer i = 1; System.out.println(i instanceof null); // false
所以,obj 的類型必須是引用類型或空類型,否則會編譯錯誤。
當 class 為 null 時,會發(fā)生編譯錯誤,錯誤信息如下:
Syntax error on token "null", invalid ReferenceType
所以 class 只能是類或者接口。
方法重載
Java 允許同一個類中定義多個同名方法,只要它們的形參列表不同即可。如果同一個類中包含了兩個或兩個以上方法名相同的方法,但形參列表不同,這種情況被稱為方法重載(overload)。
例如,在 JDK 的 java.io.PrintStream 中定義了十多個同名的 println() 方法。
public void println(int i){…} public void println(double d){…} public void println(String s){…}
這些方法完成的功能類似,都是格式化輸出。根據(jù)參數(shù)的不同來區(qū)分它們,以進行不同的格式化處理和輸出。它們之間就構(gòu)成了方法的重載。實際調(diào)用時,根據(jù)實參的類型來決定調(diào)用哪一個方法。例如:
System.out.println(102); // 調(diào)用println(int i)方法 System.out.println(102.25); // 調(diào)用println(double d)方法 System.out.println("價格為 102.25"); // 調(diào)用println(String s)方法
方法重載的要求是兩同一不同:同一個類中方法名相同,參數(shù)列表不同。至于方法的其他部分,如方法返回值類型、修飾符等,與方法重載沒有任何關(guān)系。
使用方法重載其實就是避免出現(xiàn)繁多的方法名,有些方法的功能是相似的,如果重新建立一個方法,重新取個方法名稱,會降低程序可讀性。
為什么方法重載不能用方法的返回值類型區(qū)分呢?
對于int f() { }
和void f() { }
兩個方法,如果這樣調(diào)用int result = f();,
系統(tǒng)可以識別是調(diào)用返回值類型為 int 的方法,但 Java 調(diào)用方法時可以忽略方法返回值,如果采用如下方法來調(diào)用f();
,你能判斷是調(diào)用哪個方法嗎?如果你尚且不能判斷,那么 Java 系統(tǒng)也會糊涂。在編程過程中有一條重要規(guī)則就是不要讓系統(tǒng)糊涂,系統(tǒng)一糊涂,肯定就是你錯了。因此,Java 里不能用方法返回值類型作為區(qū)分方法重載的依據(jù)。
方法重寫
在子類中如果創(chuàng)建了一個與父類中相同名稱、相同返回值類型、相同參數(shù)列表的方法,只是方法體中的實現(xiàn)不同,以實現(xiàn)不同于父類的功能,這種方式被稱為方法重寫(override),又稱為方法覆蓋。當父類中的方法無法滿足子類需求或子類具有特有功能的時候,需要方法重寫。
子類可以根據(jù)需要,定義特定于自己的行為。既沿襲了父類的功能名稱,又根據(jù)子類的需要重新實現(xiàn)父類方法,從而進行擴展增強。
在重寫方法時,需要遵循下面的規(guī)則:
- 參數(shù)列表必須完全與被重寫的方法參數(shù)列表相同。
- 返回的類型必須與被重寫的方法的返回類型相同(Java1.5 版本之前返回值類型必須一樣,之后的 Java 版本放寬了限制,返回值類型必須小于或者等于父類方法的返回值類型)。
- 訪問權(quán)限不能比父類中被重寫方法的訪問權(quán)限更低(public>protected>default>private)。
- 重寫方法一定不能拋出新的檢査異常或者比被重寫方法聲明更加寬泛的檢査型異常。例如,父類的一個方法聲明了一個檢査異常 IOException,在重寫這個方法時就不能拋出 Exception,只能拋出 IOException 的子類異常,可以拋出非檢査異常。
另外還要注意以下幾條:
- 重寫的方法可以使用 @Override 注解來標識。
- 父類的成員方法只能被它的子類重寫。
- 聲明為 final 的方法不能被重寫。
- 聲明為 static 的方法不能被重寫,但是能夠再次聲明。
- 構(gòu)造方法不能被重寫。
- 子類和父類在同一個包中時,子類可以重寫父類的所有方法,除了聲明為 private 和 final 的方法。
- 子類和父類不在同一個包中時,子類只能重寫父類的聲明為 public 和 protected 的非 final 方法。
- 如果不能繼承一個方法,則不能重寫這個方法。
抽象類
Java 語言提供了兩種類,分別為具體類和抽象類。
在面向?qū)ο蟮母拍钪?,所有的對象都是通過類來描繪的,但是反過來,并不是所有的類都是用來描繪對象的,如果一個類中沒有包含足夠的信息來描繪一個具體的對象,那么這樣的類稱為抽象類。
在 Java 中抽象類的語法格式如下:
<abstract>class<class_name> { <abstract><type><method_name>(parameter-iist); }
其中,abstract 表示該類或該方法是抽象的;class_name 表示抽象類的名稱;method_name 表示抽象方法名稱,parameter-list 表示方法參數(shù)列表。
如果一個方法使用 abstract 來修飾,則說明該方法是抽象方法,抽象方法只有聲明沒有實現(xiàn)。需要注意的是 abstract 關(guān)鍵字只能用于普通方法,不能用于 static 方法或者構(gòu)造方法中。
抽象方法的 3 個特征如下:
- 抽象方法沒有方法體
- 抽象方法必須存在于抽象類中
- 子類重寫父類時,必須重寫父類所有的抽象方法
注意:在使用 abstract 關(guān)鍵字修飾抽象方法時不能使用 private 修飾,因為抽象方法必須被子類重寫,而如果使用了 private 聲明,則子類是無法重寫的。
抽象類的定義和使用規(guī)則如下:
- 抽象類和抽象方法都要使用 abstract 關(guān)鍵字聲明。
- 如果一個方法被聲明為抽象的,那么這個類也必須聲明為抽象的。而一個抽象類中,可以有 0~n 個抽象方法,以及 0~n 個具體方法。
- 抽象類不能實例化,也就是不能使用 new 關(guān)鍵字創(chuàng)建對象。
接口
抽象類是從多個類中抽象出來的模板,如果將這種抽象進行的更徹底,則可以提煉出一種更加特殊的“抽象類”——接口(Interface)。接口是 Java 中最重要的概念之一,它可以被理解為一種特殊的類,不同的是接口的成員沒有執(zhí)行體,是由全局常量和公共的抽象方法所組成。
注意:一個接口可以有多個直接父接口,但接口只能繼承接口,不能繼承類。
定義接口
接口對于其聲明、變量和方法都做了許多限制,這些限制作為接口的特征歸納如下:
- 具有 public 訪問控制符的接口,允許任何類使用;沒有指定 public 的接口,其訪問將局限于所屬的包。
- 方法的聲明不需要其他修飾符,在接口中聲明的方法,將隱式地聲明為公有的(public)和抽象的(abstract)。
- 在 Java 接口中聲明的變量其實都是常量,接口中的變量聲明,將隱式地聲明為 public、static 和 final,即常量,所以接口中定義的變量必須初始化。
- 接口沒有構(gòu)造方法,不能被實例化。
例如:
public interface A { publicA(){…} // 編譯出錯,接口不允許定義構(gòu)造方法 }
一個接口不能夠?qū)崿F(xiàn)另一個接口,但它可以繼承多個其他接口。子接口可以對父接口的方法和常量進行重寫。例如:
public interface StudentInterface extends PeopleInterface { // 接口 StudentInterface 繼承 PeopleInterface int age = 25; // 常量age重寫父接口中的age常量 void getInfo(); // 方法getInfo()重寫父接口中的getInfo()方法 }
例如,定義一個接口 MyInterface,并在該接口中聲明常量和方法,如下:
public interface MyInterface { // 接口myInterface String name; // 不合法,變量name必須初始化 int age = 20; // 合法,等同于 public static final int age = 20; void getInfo(); // 方法聲明,等同于 public abstract void getInfo(); }
實現(xiàn)接口
接口的主要用途就是被實現(xiàn)類實現(xiàn),一個類可以實現(xiàn)一個或多個接口,繼承使用 extends 關(guān)鍵字,實現(xiàn)則使用 implements 關(guān)鍵字。因為一個類可以實現(xiàn)多個接口,這也是 Java 為單繼承靈活性不足所作的補充。類實現(xiàn)接口的語法格式如下:
<public> class <class_name> [extends superclass_name] [implements interface1_name[, interface2_name…]] { // 主體 }
對以上語法的說明如下:
public
:類的修飾符;superclass_name
:需要繼承的父類名稱;interface1_name
:要實現(xiàn)的接口名稱。
實現(xiàn)接口需要注意以下幾點:
- 實現(xiàn)接口與繼承父類相似,一樣可以獲得所實現(xiàn)接口里定義的常量和方法。如果一個類需要實現(xiàn)多個接口,則多個接口之間以逗號分隔。
- 一個類可以繼承一個父類,并同時實現(xiàn)多個接口,implements 部分必須放在 extends 部分之后。
- 一個類實現(xiàn)了一個或多個接口之后,這個類必須完全實現(xiàn)這些接口里所定義的全部抽象方法(也就是重寫這些抽象方法);否則,該類將保留從父接口那里繼承到的抽象方法,該類也必須定義成抽象類。
總結(jié)
本篇文章就到這里了,希望可以幫助到你,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
SpringBoot + FFmpeg實現(xiàn)一個簡單的M3U8切片轉(zhuǎn)碼系統(tǒng)
使用大名鼎鼎的ffmpeg,把視頻文件切片成m3u8,并且通過springboot,可以實現(xiàn)在線的點播。2021-05-05詳解Java數(shù)組擴容縮容與拷貝的實現(xiàn)和原理
這篇文章主要帶大家學習數(shù)組的擴容、縮容及拷貝,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2023-05-05詳解Spring Cloud負載均衡重要組件Ribbon中重要類的用法
本篇文章主要介紹了詳解Spring Cloud負載均衡重要組件Ribbon中重要類的用法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-03-03