java基礎第8天




繼承(extends)
1:繼承(extends)
  父類(超類、基類):被繼承特性的類就是父類。
  子類(派生類、導出類):在原有類的基本上派生出來的新類。
  
  子類可以添加自己新的屬性和方法。父類的屬性和方法也都繼承下來了!


(1)繼承的體系結構:就是對要描述的事物進行不斷的向上抽取,就出現了體系結構。
**先學習頂層內容,因爲它是共性內容。
**一般使用的時候使用的是底層的類。
(2)繼承的好處:
A:繼承的出現,提高了代碼的複用性。
B:繼承的出現,讓類與類之間產生了關係,extends來表示,
  這個關係的出現,爲後面我們講面向對象的第三個特點多態打下了基礎。
(3)特點
A:java只支持單繼承(其實確切的說是java對多繼承進行了優化,避免了安全問題)。
B:java支持多重(層)繼承。
(4)注意:
A:子類可以直接訪問父類中的非私有的屬性和行爲。
B:不要僅爲了獲取其他類中部分功能而去繼承。
C:類與類之間要有所屬( " is a " )關係,xx1是xx2的一種。
**如何判斷A和B是否有繼承關係?
**A如果繼承B,那麼就可以說A是B的一種。


2:繼承後子父類之間成員的關係
(1)成員變量
class Father
{
int num1 = 5;
}


class Son extends Father
{
int num1 = 20;
int num2 = 10;

public void show()
{
int num1 = 30;
System.out.println("num1:"+num1);
System.out.println("num2:"+num2);
//局部範圍內有的變量,如果我想使用成員變量,怎麼辦?this
System.out.println("this num1:"+this.num1);
//就想子類中訪問父類中和子類同名的變量super
System.out.println("father num1:"+super.num1);
}
}


總結:使用子類中的成員變量時,首先看局部有沒有和成員變量同門的,如果有就是用局部的。
     其實,在子類的成員變量裏面找,如果有,直接輸出。
     最後,在父類中找同名的變量,如果有,就輸出父類的值。否則報錯。


     this和super的區分:
     **this代表本類對象的引用
super代表父類的內存空間的標識。
     **this可以用於區分局部變量和成員變量同名的情況。
super可以用於區分子類和父類成員變量同名的情況。
     **一般,子類中不會出現和父類同名的成員變量。面試可能問到。


(2)成員方法
class Father
{
public void show()
{
System.out.println("father show");
}
}


class Son extends Father
{
public void show()
{
System.out.println("son show");
}


public void show1()
{
System.out.println("son show1");
}
}


總結:在使用子類的成員方法時:首先在子類中找,其次在父類中找。否則,報錯。
     super可以在子類中使用父類的成員方法。

子類中存在和父類成員方法同名的這種現象,叫做重寫,複寫,覆蓋。
重寫(override)和重載(overload)的區別:
重載的特點:
**在同一類中。
**方法名相同,參數列表不同。
重寫的特點:
**要有繼承關係。在子父類中
**方法的聲明相同。(方法名和參數列表都相同)
***覆蓋時,子類方法權限一定要大於等於父類方法權限
***靜態只能覆蓋靜態。
(3)構造方法
class Father
{

Father(){}

Fahter(int age)
{
System.out.println("father age:"+age);
}
}


class Son extends Father
{
Son()
{
//默認這裏有一個東西 super();
//this(20);
System.out.println("son");
}


Son(int age)
{
super(age);
System.out.println("son age:"+age);
}
}


Son s = new Son();  //father;son


Son s = new Son(20);//father;son age:20


總結:子類中所有的構造方法默認都會訪問父類中空參數的構造方法。
**因爲每一個構造方法的第一行都有一條默認的語句super();


     當父類中沒有空參數的構造方法時,子類的構造函數必須通過this
     或者super語句指定要訪問的構造方法。類手動提供無參構造方法。


     this(...):調用本類中的構造方法
     super(...):調用父類中的構造方法


以前:構造方法用於創建對象,並進行初始化。

     class Person
     {
Person(){}


Person(int age)
{
this.age = age;
}


Person(int age,String name)
{
this(age);
//this.age = age;
this.name = name;
}
     }


     //Person p =new Person();  //系統默認給出無參構造


     //當你手動給出構造方法後,系統就不會再給出默認的空的構造方法。



     手動無參數,如果你想給屬性賦值或者做一些初始化,無參你別刪不就行了嗎。
class Demo
{
private String name;
Demo(){}


public void setName(String name)
{
this.name = name;
}


public String getName()
{
return name;
}
}
練習繼承語法
  1.每個屬性都要有set/get方法
  兩個構造器,無參和有參(有幾個屬性就有幾個參數)
  toString(),把所有的屬性加加號連接,返回一個字符串。


  Student、Teacher
  抽取出Person
  修改Student和Teacher,繼承Person類
  再寫Employee類。
Student:int number,String name,int age,String sex
Teacher:int id, String name, int age, String sex, double salary
Person:String name,int age,String sex
Employee:int id, double salary
修改Teacher,因爲它是一個員工。它的爸爸就是Employee了,人就是爺爺!


2 畫出上面例子的繼承層次圖


  可以嘗試再添加一些類,例如:


繼承了什麼
  構造器是繼承不了的。
  private的屬性和方法也是無法繼承的。(private屬性是不能用,但其實子類是有的)(如果有人考你,子類是否繼承了父類的private屬性,你回答“沒有”)
  其他的屬性和方法就都繼承下來了。




多態性(崔老師)
員工類,有一個返回年終獎的方法,但這個方法是空的。
經理,重寫了這個方法;
祕書,重寫了這個方法;
程序員,重寫了這個方法;
業務員,也重寫了了這個方法;
我們用一個員工數組來把這些經理、祕書、等等都放這個數組中。
循環遍歷這個數組,調用每個元素的返回年終獎方法,做累加和,計算年底要發的工資。


員工[] es = new 員工[100];//這是一百個員工引用!
es[0] = new 經理();//向上轉型
es[1] = new 祕書();
….
es[0].返回年終獎(),這是調用經理的方法。


1 是一個(is a),向上轉型
  可以用父類的引用,指向子類的實體對象。
  只有向上轉型了,纔會有多態,所以,我們經常會說向上轉型,就是多態!


2 調用的是子類的方法還是父類的方法
  調用誰的方法,由實體類型來決定,而不是引用類型。


3 向上轉型後能調用的方法個數被引用類型限制
  調用的方法是實體的方法,但能調用的方法個數受引用類型的限制。


4 向下轉型不安全
  向上轉型:用父類的引用指向子類引用指定的實體。這是安全的!
  向下轉型:用子類的引用指向父類引用指向的實體。這是不安全的!






非靜態
S.fun() p.fun()調用誰的方法,由實體類型來決定,而不是引用類型。
S.fun() p.fun()的區別p的那個只能調用重寫父類的方法,s既可以調用重寫,也可以調用自己的
靜態的(static)
誰調用的就用誰!






5 判斷“是一個”的關係(instanceof運算符)




6 多態調用的概念
  重載:編譯器確定要調用的是哪一個方法。同一條調用語句,但調用的哪個重載版本的方法是多態的!
  重寫:JVM確定調用的是哪一個方法。同一個類型的引用,調用的是哪個類的方法是多態的!


public void fun(byte b) {}


public void fun(int i) {}


byte b = 1;
fun(b);
7 運行時多態的前提
繼承或實現;
重寫方法
向上轉型,然後調用重寫方法。


錯誤的多態理解


1 屬性不是多態的




2 static方法不是多態的




3 private方法不是多態的


多態(沙老師)
(1)某一類事物的多種存在形態。
**方法重載(靜態多態)
**方法重寫(動態多態,對象多態)
(2)對象多態的前提
A:類與類(或接口)要有繼承(或實現)關係。
B:一定要有方法的重寫。
C:一定要有父類或者接口的引用指向子類的對象。
(3)多態思想:可以指揮同一類型的一批對象做事情。多態的出現讓我們複雜的問題簡單化了。
A:Animal Cat Dog
**method(Animal a){a.eat();}
B:同學們喫飯
C:士兵打仗(擡槍,瞄準,射擊)。
(4)多態中成員的特點:(我們只研究特殊的,就是說名字一樣的東西)
Fu f = new Zi();
A:成員變量:編譯和運行都看Fu。
B:非靜態方法:編譯看Fu,運行看Zi。
C:靜態方法:編譯和運行都看Fu。

舉例: 動物的例子:
向上轉型
Animal a = new Cat();
a.eat();
//a.catchMouse();


向下轉型
Cat c = (Cat)a;
c.eat();
c.catchMouse();


//向上轉型
Animal a = new Dog();
//向下轉型 轉換異常
//Cat c = (Cat)a;
Dog d = (Dog)a;


孔爹的例子:
孔爹:教課(Java)
孔子:教課(論語),看小說(),打遊戲()。


孔爹 k = new 孔子();//穿上他爹衣服,就跟着去了
k.教課(論語)。
//k.看小說();


孔子 kz = (孔子)k;//把衣服脫了
kz.教課(論語);
kz.看小說();
kz.打遊戲();




final可以用來修飾什麼呢?
(1)final可以用來修飾類:被fainl修飾的類不能被繼承。
(2)final可以用來修飾成員方法:被final修飾的成員方法不能被重寫。
(3)final可以用來修飾變量:被final修飾的變量爲常量,值不能被修改。
  常量的命名規範:要求大寫。
  final int PI = 3.14;


  final難道必須聲明的時候就賦值。
  一般來說,是這樣的。但是特殊情況:在構造方法可以給final修飾的變量賦值。


Object
(1)Object類:java中所有類的父類。它是java類體系結構中的根類。
    java中的類都直接或者間接繼承自Object類。
(2)學習了裏面的幾個方法:重點掌握 toString(),equals()。
boolean equals(Object o):比較當前對象和參數對象是否相等!但這個比較沒有什麼意義!因爲我們希望比較的不是兩個引用是否指向同一個實體,而是想知道這兩個實體是否一樣!
int hashCode():返回一個整數,它表示一個對象實體的地址。或者你可以理解爲它是地址運算後的結果。這個方法會在集合時再討論!
String toString():返回一個對當前對象的描述,即字符串形式的描述!Object類的toString()返回的是當前對象的“類全名 + @ + 16進制的hashCode()”
Class getClass():返回當前對象的類型信息,其中返回值Class類型,它就是方法區的.class文件對應體!


A:boolean equals(Object obj) 
  指示其他某個對象是否與此對象“相等”。 
B:String toString() 
  返回該對象的字符串表示。 
C:int hashCode() 
  返回該對象的哈希碼值。 
D:Class<?> getClass() 
  返回此 Object 的運行時類。 
E:protected void finalize() 瞭解
  當垃圾回收器確定不存在對該對象的更多引用時,由對象的垃圾回收器調用此方法。 
  **final,finally,finalize
(3)重點看下面兩個方法
//重寫toString()方法
public String toString()
{
//return "HelloWorld";
return "name:"+name+",age"+age;
}


//重寫Object的equals方法
public boolean equals(Object obj)//s2--obj
{
//爲了提高效率
if(this == obj)
{
return true;
}


//爲了程序的健壯性
if(!(obj instanceof Student))//格式:對象 instanceof 具體的類名
{
return false;
}


Student s = (Student)obj;
if(this.age==s.age)
{
return true;
}
else 
{
return false;
}
}
"equals"和"=="用法區別?
equals()是一個方法,來自Object類
==比較運算符,叫關係運算符!
==用來比較基本類型,但比較引用類型,那麼比較的是兩個引用的地址是否相同
equals()是一個方法,它比較當前對象和參數對象是否相等,在Object類中,就是使用==來比較的,
所以,調用Object類的equals()和使用==比較,是相同效果!
但,很多子類都重寫了equals()方法,那麼比較的效果就與==不同了。
結論:基本類型使用==比較
引用類型使用equals()比較!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章