java面向对象——包+继承+多态(一)
文章目錄
- 包(package)
- 概念:
- 創建包
- 注意事項:
- 導入包中的類:
- 直接導入
- import語句導入
- 注意事項:
- 靜態導入(了解即可)
- 包的訪問權限
- 常見的系統包
- 繼承
- 繼承的語法規則
- 注意要點:
- super關鍵字(重點)
- 1 super()幫助父類進行構造
- 注意事項:
- 2 super.func()調用父類的普通方法
- 3 super.data引用父類實例
- super關鍵字與this關鍵字的區別:
- protected關鍵字(重點)
- 1 在同一個類中
- 2 在同一個包中在不同的類
- 3 不同包底下的子類
- 4 不同包底下的非子類
- 訪問權限的總結
- 更復雜的繼承關系:(了解)
- 多態:
- 向上轉型(重點)
- 向上轉型發生的時機:
- 動態綁定(重點)
- 發生的條件:
- 靜態綁定:
- 重寫的注意事項
- 重寫與重載的區別
- 結語:
包(package)
概念:
是組織類的一種方式,能夠保證類的唯一性
創建包
在src包下點擊new 然后package創建包,就能夠創建出一個包,在創建的包下新建java class就會創建一個類。
注意事項:
1 在文件的最上方加上一個 package 語句指定該代碼在哪個包中,比如創建一個class的包,在這個包下新建的java文件,要在最上方加上package class(IDEA一般會自動生成)
2 如果一個類沒有 package 語句, 則該類被放到一個默認包中
3 包名需要盡量指定成唯一的名字
導入包中的類:
直接導入
public class testdemo {public static void main(String[] args) {java.util.Date date=new java.util.Date();// 得到一個毫秒級別的時間戳System.out.println(date.getTime());} }這種導入就需要我們知道,我們調用的類在那個包目錄下,而且這樣子也很麻煩,在這里作為一個了解就可以。
import語句導入
import java.util.Date; public class testdemo {public static void main(String[] args) {Date date=new Date();// 得到一個毫秒級別的時間戳System.out.println(date.getTime());} }當我們對Date這個類實例化的時候,我們可以發現,IDEA會自動提示出這個類所在的包,此時我們只需要雙擊一下java.util(在這里,要特別提一下,不同的包里面的類名是可以一樣的,我們語句中時間戳的功能,是在java.util這個包下的Date類實現的,這個問題不需要深究,只需要理解利用import是怎么導入包中的類),這個時候就會自動幫我們導入包中的類。
上面所講的就是通過import語句導入包中具體類名稱,其實也可以使用java.util.*;導入,代碼也不會報錯
這個可以理解是一個通配項,這樣子確實會比較方便,也很簡單,但是我們并不建議這樣子去導入包中的類,最好要具體到類名
import java.util.*; import java.sql.*;public class testdemo {public static void main(String[] args) {Date date=new Date();// 得到一個毫秒級別的時間戳System.out.println(date.getTime());} }如果此時導入java.util與java.sql包那么此時Date就會報錯,原因就是util與sql包下都有一個Date類,那么此時編譯器就懵逼了,就不知道導入的是誰的了,那么此時就需要我們導入具體的一個類名就不會報錯了
注意事項:
1 不同與c語言,java在使用通配項的時候,不是把包下的所有類都導入進去,是需要哪一個類,才會使用哪一個類,而c語言是把所有的類全部導入
2 包名必須是小寫字母
3 在導入包中的類的時候,要導入具體的類名稱,養成良好的編程習慣。
靜態導入(了解即可)
使用 import static 可以導入包中的靜態的方法和字段.
import static java.lang.System.*; import static java.lang.Math.*; public class testdemo {public static void main(String[] args) {Date date=new Date();// 得到一個毫秒級別的時間戳out.println(date.getTime());out.println(max(2,3));} }取最大值的時候,如果沒有調用使用靜態導入就必須得是math.max(2,3),可以看到system以及math就可以省略掉了,這就是靜態導入。
包的訪問權限
在java的類與對象中,我們已經初步認識到類中的public與priate訪問限定符,包訪問權限就是不加任何關鍵字去修飾,直接定義其類型。訪問的范圍:只能在同一個包中。
常見的系統包
繼承
class dog{public String name;public int age;public void eat(){System.out.println("eat()");} } class bird{public String name;public int age;public void eat(){System.out.println("eat()");}public void fly(){System.out.println("fly()");} } public class test {public static void main(String[] args) {dog dog=new dog();dog.name="haha";bird bird=new bird();bird.name="heihei";bird.fly();} }在上面這個代碼我們可以看到,對于bird以及dog類中都含有共同的字段與方法,那么這個時候我們就可以通過繼承來對代碼實現重復利用(對代碼的共同屬性進行抽取)
class animal{public String name;public int age;public void eat(){System.out.println("eat()");} } class dog extends animal{ } class bird extends animal{public void fly(){System.out.println("fly()");} } public class test {public static void main(String[] args) {dog dog=new dog();dog.name="haha";bird bird=new bird();bird.name="heihei";bird.fly();} }在這里我們可以發現,繼承是由關鍵字extends來引出的,其中dog,bird我們稱之為子類,派生類,animal我們稱之為父類,基類,超類
繼承的語法規則
class 子類 extends 父類 {
}
注意要點:
1 通過關鍵字extends指定父類
2 java中只能繼承一個父類
3 子類會繼承父類中所有的字段與方法
4 對于private修飾的字段,子類是不能訪問的
5 子類的實例中, 也包含著父類的實例. 可以使用 super 關鍵字得到父類實例的引用.
6 如果一個類不想被繼承,那么可以使用關鍵字final去修飾這個類
super關鍵字(重點)
1 super()幫助父類進行構造
在利用構造方法對子類進行構造時,必須要先幫助父類進行構造
class animal{public String name;public int age;public void eat(){System.out.println(name+"eat()"+age);}public animal(String name,int age){this.name=name;this.age=age;eat();}public void func(){System.out.println("");} } class dog extends animal{public dog(String name,int age){super(name,age);//調用父類含有兩個參數的構造方法} } class bird extends animal{public bird(String name,int age){super(name,age);//調用父類含有兩個參數的構造方法}public void fly(){System.out.println("fly()");} } public class test {public static void main(String[] args) {dog dog=new dog("haha",10);bird bird=new bird("heihei",20);} }注意事項:
1 super在幫助子類構造父類的時候,super()必須處于子類構造方法的第一行
2 super表示父類的實例引用,是依賴于對象的,所以是不能出現在靜態方法里面的
2 super.func()調用父類的普通方法
class animal{public String name;public int age;public void eat(){System.out.println(name+"eat()"+age);}public animal(String name,int age){this.name=name;this.age=age;}public void func(){System.out.println("");} } class dog extends animal{public dog(String name,int age){super(name,age);super.eat();} }在這個代碼中,我們可以看到在子類中可以利用super關鍵字調用父類普通方法,這里要注意super在調用父類的方法時不能寫出方法外面的
3 super.data引用父類實例
這個就是在子類中,通過super關鍵字去訪問父類的字段
super關鍵字與this關鍵字的區別:
1 super是在父子類的前提下,作用在子類,在子類里去訪問父類的方法與字段,并且要先幫助父類構造方法,必須放在第一行
2 this關鍵字查找范圍在本類中或者是本類中沒有就去父類中查找,通過this可以調用本類中的字段(本類中要是沒有就會去父類中查找),調用本類中的方法(本類要是沒有,就會去父類中查找),也可以在本類調用構造方法,調用構造方法需要放在方法的第一行
protected關鍵字(重點)
1 在同一個類中
public class time {protected int val = 99;public static void main(String[] args) {time time=new time();System.out.println(time.val);} }此時代碼能夠正常執行
2 在同一個包中在不同的類
可以看到test與time是在同一個包底下的不同的類,test是可以訪問到protected修飾的val
3 不同包底下的子類
在不同包底下,我們要在子類中導入父類,在進行繼承,由于是父子類關系,我們要用super關鍵字對父類中的實例進行訪問(super關鍵字是不能出現在靜態方法中的,因為super是對父類對象的引用,是依賴于對象的,而靜態方法是屬于類的,不依賴于對象)
4 不同包底下的非子類
很明顯這是不能進行訪問的
訪問權限的總結
結合之前我們前面所講過的public,private,以及包訪問權限,現在所學的protected,我們進行一個總結
private:只能在類的內部使用,外部不能進行訪問
public:類的外部與內部,同一個包或者不同包下都能進行訪問
default(包訪問權限):只能在同一個包中進行訪問
protected:同一個包,同一個類,不同包的父子類之間都可以進行訪問,在父子類中要利用super關鍵字進行訪問,不同包的非子類是不能進行訪問的
更復雜的繼承關系:(了解)
我們剛才所例舉的動物中,對于貓也分為很多種,比如國內的貓種以及國外的貓種,國內的貓種又可以分為那幾種等還可以繼續細分下去,這種繼承關系必須要有邏輯上的聯系,不能僅僅為了繼承而繼承。一般而言我們對于這種復雜的繼承關系,一般最好不要超過3層
多態:
向上轉型(重點)
具體可以看下下列代碼
bird bird=new bird(“heihei”,20);
在上面的例子中我們我們知道bird是bird的一個引用,它可以寫成下列這種形式
bird bird=new bird(“heihei”,20);
animal bird2 = bird;
//或者寫成這個樣子
animal bird2 = new bird(“heihei”,20);
此時這種寫法就被稱作向上轉型,也就是父類的引用去引用了子類的對象。
向上轉型發生的時機:
1 直接賦值法
這個方法其實就是我們剛才在介紹向上轉型的時候所介紹的那個例子。
2 作為返回值
3 方法的參數
public static void main(String[] args) {bird bird =new bird("aio",39);func(bird);}public static void func(animal animal){animal.eat();}動態綁定(重點)
發生的條件:
1 發生了向上轉型(父類引用引用了子類的對象)
2 通過父類的引用,調用父類與子類同名的覆蓋方法
動態綁定也被叫做運行時多態(至于具體什么是多態,在下文會具體介紹),也就是在運行時才確定調用的是子類的eat方法
我們首先可以從main函數入手,可以看到,animal調用用eat方法,可以看到并沒有執行父類中的eat方法,而是調用了子類中同名且參數相同,返回值相同的eat方法,此時我們就說發生了動態綁定,而eat方法也被稱作覆蓋方法,在這個過程我們就說eat發生了重寫,并且可以用@override進行標注
靜態綁定:
與動態綁定不同,靜態綁定在編譯時就確定調用了子類的eat方法
public class blos {public static void main(String[] args) {duck duck=new duck();duck.fun("haha");} } class duck{public void fun(){System.out.println("無參");}public void fun(String name){System.out.println("一個參數");}public void fun(String name,int age){System.out.println("兩個參數");} }當duck調用fun方法時,給fun傳了幾個參數,就對應調用那個方法,這個時候我們就說發生了靜態綁定,可以知道靜態綁定則需要發生在重載的情況下,而動態綁定則需要先發生重寫。
重寫的注意事項
1 被final修飾的方法不能發生重寫
2 被private修飾的方法不能重寫
3 被static修飾的方法不能重寫
4 子類方法的修飾限定符要大于父類的修飾限定符
重寫與重載的區別
1 重寫的返回值要一樣(這里有個特殊情況,就是可以是協變類型也是可以的),重載是與返回值無關的
2 重寫與重載的方法名都要相同的
3 重寫的方法參數要一致,重載的方法參數要不同(這里的方法參數包括含參種類以及含參的個數)
結語:
在后面的一篇文章中,我們會繼續詳細的講解什么是多態,什么是抽象類,什么是接口。希望本篇文章能夠對于你有所幫助!總結
以上是生活随笔為你收集整理的java面向对象——包+继承+多态(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 快速入门无头双链表
- 下一篇: 详解单链表经典OJ题