java就是一個面向對象的思想,而面向對象有三大特性:
- 封裝
- 繼承
- 多態
封裝
1,定義:
封裝把一個對象的屬性私有化,同時提供一些可以被外界訪問的屬性的方法。
2,好處:
1,實現了低耦合高內聚。
2,類內部的結構可以自由修改。
3,隱藏實現細節,提供公共的訪問方式。
繼承
1,概述:
繼承就是子類繼承父類的特徵、行爲,體現了類與類之間的"is-a"關係。A類是B類的父類,可以說B類是A類的子類,B類繼承了A類各種的方法和屬性(私有化的除外)。子類繼承父類的同時,可以重新定義某些屬性,並重寫某些方法,即覆蓋父類的原有屬性和方法,使其獲得與父類不同的功能。
繼承通過關鍵字extends實現。
java.lang.Object類是所有類的父類
2,限制:
1,java中繼承是單繼承,即一個子類只能繼承一個父類。
2,支持多重繼承,即一個父類可以有多個子類。
3,繼承只能繼承非私有化的屬性和方法。
4,構造方法不能被繼承。
3,格式:
class 子類名 extends 父類名{}
案例:
public class Animal{
String name;
String age;
public void eat(){
Sysotem.out.println(name+"動物在吃肉"+age)
}
}
public class cat extends Animal{
Cat cat = new Cat();
c.name="tOM";
c.age=18;
p.eat();
}
輸出:
4,子類滿足重寫父類方法的要求
- 重寫方法與被重寫方法必須具有相同的方法名。
- 重寫方法與被重寫方法必須具有相同的參數列表。
- 重寫方法的返回值類型必須和被重寫方法的返回值類型相同
- 重寫方法不能縮小被重寫方法的訪問權限。
5,重寫方法和重載的區別和聯繫
重載涉及同一個類中的同名方法,要求方法名相同,要求參數列表不同,與返回值類型,訪問修飾符無關,而重寫涉及的是子類和父類之間的同名方法,要求方法名稱相同,參數列表相同,
6,方法重載
- 當子類繼承父類時,可以從父類繼承它的屬性和方法。
- 如果從父類繼承的方法不能滿足子類的需求,可以對其進行改寫,這個過程叫方法的覆蓋(override),也稱爲方法的重寫。
- 當對父類的方法進行重寫時,子類中的方法必須和父類中對應的方法具有相同的方法名稱、輸入參數(包括參數的個數和類型)和返回值。
- 子類中的覆蓋方法不能使用比父類中被覆蓋方法更嚴格的訪問權限。
7,構造器
父類的構造器只能夠被調用,而不能被子類繼承。
如果父類沒有構造器,java會給出一個默認構造器。父類帶有一個帶參的構造器,子類必須通過super關鍵字來調用父類的構造器並配以相關的參數。
父類構造器沒有參數,則在子類的構造器中不需要使用 super 關鍵字調用父類構造器,系統會自動調用父類的無參構造器。
創建父類:
class Animal{
private Integer high;
public Animal() {
System.out.println("Animal()");
}
public Animal(Integer high) {
System.out.println("Animal(Integer high)");
this.high = high;//this表示對該對象的引用
}
// set、get方法
public Integer getHigh() {
return high;
}
public void setHigh(Integer high) {
this.high = high;
}
}
創建子類:
class Dog extends Animal{
private String name;
public Dog() {
System.out.println("Dog()");
}
public Dog(String name) {
this.name = name;
System.out.println("Dog(String name)");
}
public Dog(Integer high) {
super(high);
System.out.println("Dog(Integer high)");
}
public Dog(Integer high, String name) {
super(high);
this.name = name;
System.out.println("Dog(Integer high, String name)");
}
// set、get方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
創建測試類:
public class MyMain {
public static void main(String[] args) {
System.out.println("- - - - - - - new Dog() - - - - - - -");
Dog dog = new Dog();
System.out.println("- - - - - - - new Dog(Integer high) - - - - - - -");
Dog highDog = new Dog(180);
System.out.println("- - - - - - - new Dog(String name) - - - - - - -");
Dog nameDog = new Dog("張二狗");
System.out.println("- - - - - - - new Dog(Integer high, String name) - - - - - - -");
Dog highNameDog = new Dog(180,"張二狗");
}
}
結果:
- - - - - - - new Dog() - - - - - - -
Animal()
Dog()
- - - - - - - new Dog(Integer high) - - - - - - -
Animal(Integer high)
Dog(Integer high)
- - - - - - - new Dog(String name) - - - - - - -
Animal()
Dog(String name)
- - - - - - - new Dog(Integer high, String name) - - - - - - -
Animal(Integer high)
Dog(Integer high, String name)
1.子類通過super調用父類構造器
子類通過super()調用父類無參構造器;通過super(參數)調用父類有參構造器;如果不寫super,子類默認調用父類無參構造器
2.子類創建對象時,父類構造器會先執行。
super必須放在子類構造器內第一行,否則會報錯。
3,多態
同一個對象在不同時刻體現出來的不同狀態。例如,動物中有貓和狗,都有吃這個共性,而貓吃魚,狗吃骨頭。
繼承的前提:
- 繼承
- 重寫
- 父類引用指向子類對象
當提到多態時,不得不提出向上轉型。
class Animal{}
class Dog extends Animal{}
Animal a = new Dog()//向上轉型
將子類轉換成父類,在繼承關係上面是向上移動的,所以一般稱之爲向上轉型。
在這裏我們這樣理解,這裏定義了一個 Animal 類型的a,它指向 Dog 對象實例。由於Dog 是繼承 Animal,所以 Dog 可以自動向上轉型爲Animal,所以 a 是可以指向Dog 實例對象的。這樣做存在一個非常大的好處,在繼承中我們知道子類是父類的擴展,它可以提供比父類更加強大的功能,如果我們定義了一個指向子類的父類引用類型,那麼它除了能夠引用父類的共性外,還可以使用子類強大的功能。
但是向上轉型存在一些缺憾,那就是它必定會導致一些方法和屬性的丟失,而導致我們不能夠獲取它們。所以父類類型的引用可以調用父類中定義的所有屬性和方法,卻不能調用子類中的方法和屬性。
當使用多態方式調用方法時,首先檢查父類中是否有該方法,如果沒有,則編譯錯誤;如果有,再去調用子類的同名方法。這是多態的一個弊端:不能使用子類特定的功能
public class test {
public static void main(String[] args) {
father people = new son();
people.speak();
System.out.println("i am "+people.getAge());
people.play();
}
}
class father{
private int age ;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void speak() {
System.out.println("i am father !");
}
}
class son extends father{
public son() {
setAge(17);
}
public void speak(){
System.out.println("i am son !");
}
public void play(){
System.out.println("i am son , i want to play!");
}
}
這個例子的結果會報錯,因爲父類沒有play()方法。對於子類中存在而父類中不存在的方法,該引用是不能使用的,儘管是重載該方法。
實現多態的方式:
- 接口多態性
- 繼承多態性
- 通過抽象類實現的多態性
4,多態和繼承的區別
繼承:子類繼承父類中所以的屬性和方法,但是對於private的屬相和方法,由於這個是父類的隱私,所以子類雖然是繼承了,但是沒有可以訪問這些屬性和方法的引用,所以相當於沒有繼承到。很多時候,可以理解爲,沒有繼承。
多態:就是父類引用可以持有子類對象。這時候只能調用父類中的方法,而子類中特有方法是無法訪問的,因爲這個時候(編譯時)你把他看作父類對象的原因,但是到了運行的時候,編譯器就會發現這個父類引用中原來是一個子類的對像,所以如果父類和子類中有相同的方法時,調用的會是子類中的方法,而不是父類的。可以這麼說:編譯時看父類,運行時看子類。