不定期更新夕春,歡迎指正
1. 重載污呼、重寫和隱藏
1). 重載(overload):
方法重載就是多個方法名稱相同但是參數(shù)類型或者參數(shù)個數(shù)不同的方法银择,與返回值類型和修飾符無關(guān)
class Test {
public int test(int a) {
return a;
}
public String test(String a) {
return a;
}
public float test(int a, String b) {
return 0f;
}
public float test(String a, int b) {
return 1.0f;
}
String test(float a) {
return "";
}
String test(int a) {//該方法不是重載
return "";
}
}
前面五個互為重載斑司,第一個和第六個雖然返回值類型不同妙蔗,但參數(shù)相同,所以第一個和第六個參數(shù)不是重載
2). 重寫(override):
子類繼承父類時免猾,子類的方法名稱是辕、參數(shù)類型、參數(shù)個數(shù)與父類完全相同猎提,則認為子類重寫了父類的方法获三。
方法重寫規(guī)則:
- 參數(shù)列表和原方法完全相同
- 返回值類型和原方法相同或者為父類返回值類型的子類型
- 不能比原方法限制更嚴格的訪問級別(舉例:父類方法為public,那么子類不能為protected锨苏、private)
- 父類方法被定義為final時疙教,則不能被重寫
- 父類方法被定義為static時,不能被重寫伞租,但是可以重寫聲明一個相同的方法(參考隱藏)
- 不能拋出新的異痴晡剑或比原方法更廣泛的異常(父類拋出IOException,重寫方法不能拋出Exception只能拋出IOException或者IOException子類異常)
3). 隱藏:
隱藏是針對于父類的成員變量和靜態(tài)方法而言的葵诈。子類中聲明了和父類相同的變量名或靜態(tài)方法(方法名相同裸弦、參數(shù)列表相同、返回類型相同)則實現(xiàn)了對父類成員變量和靜態(tài)方法的隱藏作喘,下面舉個例子有助理解:
class A {
static int a = 1;
static int b = 2;
int c = 33;
public static void printA() {
System.out.print(a);
}
public static void printB() {
System.out.print(b);
}
}
class B extends A {
static int a = 3;
static int b = 4;
int c = 44;
public static void printB() {
System.out.print(b);
}
}
public class Test {
public static void main(String[] args) {
B.printA();
B.printB();
System.out.print(B.a);
A a = new B();
B b = new B();
a.printB();
b.printB();
System.out.print(a.c);
System.out.print(b.c);
}
}
輸出結(jié)果:
1 4 3 2 4 33 44
如果子類中有相同名稱的靜態(tài)方法或變量父類的會被隱藏理疙,如果子類中存在同名的靜態(tài)方法或變量,則會隱藏父類中得靜態(tài)方法或變量泞坦,此時子類調(diào)用的就是子類中自己的靜態(tài)方法或變量窖贤;如果子類中不存在同名的靜態(tài)方法或變量,則會調(diào)用父類中的靜態(tài)方法或變量;父類調(diào)用的始終是其本身的靜態(tài)方法和變量赃梧。
2. 封裝:
封裝是把對象的屬性和操作結(jié)合為一個獨立的整體择吊,隱藏對象內(nèi)部操作的實現(xiàn),用戶只需要通過其對外提供的方法來訪問該對象槽奕,無需知道其內(nèi)部實現(xiàn)細節(jié)几睛。
優(yōu)點:
- 隱藏內(nèi)部實現(xiàn)細節(jié),提供公共訪問方式
- 類內(nèi)部可以自由修改不影響其調(diào)用者
- 減少耦合度粤攒,提高安全性
3. 繼承:
繼承是一個對象獲取另一個對象屬性的過程所森,關(guān)鍵字為extends
和implements
。
1). IS-A關(guān)系(一個對象所屬于另一個對象):
方式一. 用extends來實現(xiàn)繼承:
public class Animal {
public void eat() {
System.out.println("Animal eating...");
}
}
public class Mammal extends Animal {
public void eat() {
System.out.println("Mammal eating...");
}
}
public class Dog extends Mammal {
public void eat() {
System.out.println("Dog eating...");
}
}
方式二. 用implements來實現(xiàn)繼承:
public interface Animal {
void eat();
}
public class Mammal extends Animal {
public void eat() {
System.out.println("Mammal eating...");
}
}
public class Dog extends Mammal {
public void eat() {
System.out.println("Dog eating...");
}
}
無論方式一還是方式二夯接,我們都可以用instanceof關(guān)鍵字檢查得出:Mammal是一個Animal(哺乳動物也是動物)焕济;Dog既是一個Mammal,也是一個Animal(狗既是哺乳動物也是動物)盔几。
public class Test {
/**
* instanceof關(guān)鍵字檢查代碼
*/
public static void main(String[] args) {
Mammal m = new Mammal();
Dog d = new Dog();
System.out.print(m instanceof Animal);
System.out.print(d instanceof Mammal);
System.out.print(d instanceof Animal);
}
}
輸出結(jié)果:
true true true
2). HAS-A關(guān)系(一個對象含有另一個對象的一些屬性):
public class Car{}
public class Speed{}
public class Benz extends Car{
private Speed sp;
}
Benz含有Spend屬性晴弃,但Benz不是Spend
4. 多態(tài):
實現(xiàn)多態(tài)的三個必要條件:繼承、重寫逊拍、父類引用指向子類對象上鞠。
1). 向上轉(zhuǎn)型:
我們實例化一個Dog對象可以用 Dog d = new Dog();
我們也可以用 Animal d = new Dog();
,后者就是向上轉(zhuǎn)型(父引用指向子對象)芯丧,上面兩種方式創(chuàng)建出來的對象d芍阎,調(diào)用d.eat();
輸出的結(jié)果都是Dog eating...
,這就體現(xiàn)出了java得多態(tài)缨恒。向上轉(zhuǎn)型創(chuàng)建的對象會遺失掉和父類不同的方法和變量(不能用來調(diào)用子類特有的方法和變量)谴咸。
2). 舉例說明:
class A {
public String show(D obj) {
return ("A and D");
}
public String show(A obj) {
return ("A and A");
}
}
class B extends A {
public String show(B obj) {
return ("B and B");
}
public String show(A obj) {
return ("B and A");
}
}
class C extends B {}
class D extends B {}
class Test {
public static void main(String[] args) {
A a1 = new A();
A a2 = new B();
B b = new B();
C c = new C();
D d = new D();
System.out.println(a1.show(b)); // ①
System.out.println(a1.show(c)); // ②
System.out.println(a1.show(d)); // ③
System.out.println(a2.show(b)); // ④
System.out.println(a2.show(c)); // ⑤
System.out.println(a2.show(d)); // ⑥
System.out.println(b.show(b)); // ⑦
System.out.println(b.show(c)); // ⑧
System.out.println(b.show(d)); // ⑨
}
}
輸出結(jié)果:
A and A // ①
A and A // ②
A and D // ③
B and A // ④
B and A // ⑤
A and D // ⑥
B and B // ⑦
B and B // ⑧
A and D // ⑨
前三個比較簡單不容易出錯,看看下面幾個:
- ④:a2是A的引用指向B對象骗露,向上轉(zhuǎn)型創(chuàng)建的對象會遺失掉和父類不同的方法和變量岭佳,所以a2只能調(diào)用
show(D obj)
、show(A obj)
兩個方法萧锉,所以a2.show(b)
應(yīng)該調(diào)用show(A obj)
方法珊随,B中重寫了該方法,所以運行時JVM會調(diào)用B類中重寫的show(A obj)
方法驹暑,所以輸出B and A
玫恳; - ⑤: 原理同④;
- ⑥:
a2.show(d)
應(yīng)該調(diào)用show(D obj)
方法优俘,B中沒有重寫該方法所以調(diào)用的為A類中的該方法,所以輸出為A and D
; - ⑦⑧⑨:b為B類對象掀序,可調(diào)用A類中
show(D obj)
帆焕、B類中show(B obj)
、B類中show(A obj)
方法,所以輸出如上叶雹。