一.繼承:
關(guān)鍵字extends
/*
定義一個父類:人類
定義父類格式:public class 父類名稱{
}
定義子類格式:public class 子類名稱 extends 父類名稱{
}
*/
-
代碼示范:
*
在這里插入圖片描述要點:
1.子類中在main方法中創(chuàng)建父類對象可調(diào)用父類方法;
2.不加關(guān)鍵字直接訪問本方法局部變量(可重名時區(qū)分);
3.使用this關(guān)鍵字訪問本類成員變量(可重名時區(qū)分);
4.使用super關(guān)鍵字訪問父類成員變量(可重名時區(qū)分);
5.如果存在方法的重名:父類與子類有重名方法:
——對象new的誰則優(yōu)先調(diào)用誰的重名方法,沒有則向上尋找;
前面介紹了成員變量、成員方法繼承的訪問特點,接下來是構(gòu)造方法:
——子類構(gòu)造方法(父類無參時)中有一個默認(rèn)贈送的super()方法
——父類有參時,子類里調(diào)用super的()里傳參,重載時誰對的上調(diào)用誰;
6.如果要更新修改父類方法,本著設(shè)計原則盡量不去直接修改正在使用的類,
則可以進(jìn)行覆蓋重寫:格式:通過使用super關(guān)鍵字繼承父類需要的方法。
@Override
方法外部相同(){
super.父類方法();
//這里添加新的內(nèi)容
}
/*
小結(jié)super
super關(guān)鍵字作用:
示例:
public class demo06Super extends demo01people {
public void method1(){
System.out.println(super.num); //1.在子類成員方法中訪問父類的成員變量
}
public void method2(){
super.methodChongMing(); // 2.在子類成員方法中訪問父類的成員方法
}
public demo06Super(){
super(); //3.在子類的構(gòu)造方法中訪問父類的構(gòu)造方法
}
}
*/
7.this關(guān)鍵字的作用小結(jié):
this關(guān)鍵字的作用:
1.在本類的成員方法中訪問本類的成員變量
2.在本類成員方法中訪問本類的另一個成員方法
3.在本類的構(gòu)造方法中訪問本類的另一個構(gòu)造方法:
(1)this(...)調(diào)用必須是構(gòu)造方法的第一個語句,一個this;
(2)super和this兩種構(gòu)造調(diào)用不能同時使用
- 代碼示范:
String name = "python";
public void method1(){
String name = "python";
System.out.println(name);//無關(guān)鍵字時直接訪問本方法局部變量
System.out.println(this.name);//訪問本類成員變量
System.out.println(super.num);//訪問父類成員變量
this.method2();//訪問本類另一個成員方法
}
8.最后,繼承三大特點:
1.單繼承:一個子類只有一個直接父類
2.多級繼承:父類、子類、子類也可作父類再向下延伸,最上級為java.lang.object類
3.一個父類可以有多個子類
二、多態(tài)
1.多態(tài)性:父類引用指向子類對象
多態(tài)的一個用處:無論右邊new的時候換成哪個子類對象,等號左邊調(diào)用方法都不會發(fā)生變化
格式:
父類名稱 對象名 = new 子類名稱();
或者:
接口名 對象名 = new 實現(xiàn)類名稱()。
2.成員方法:編譯看左,運行看右;
成員變量:編譯看左,運行也看左;實例變量不具備多態(tài)性.
代碼示范:
//前面省略部分Zi類已經(jīng)繼承Fu類
public static void main(String[] args) {
Fu one = new Zi();//多態(tài)的寫法
one.methodcommon();//重名時,成員方法優(yōu)先使用子類(new誰先調(diào)用誰)。
one.fu1();//它的編譯時類型為Fu,可以調(diào)用Fu中的方法
// one.zi1(); 該調(diào)用編譯時會報錯,因為它的編譯時類型為Fu,無法調(diào)用zi1方法;
System.out.println(one.num);//優(yōu)先看左邊Fu類
Zi two = (Zi) one;//將父類對象還原成子類對象。
System.out.println(one instanceof Fu);//輸出true,one可以做Fu類的實例對象
System.out.println(one instanceof Zi);//輸出true,one可以做Zi類的實例對象
}
3.轉(zhuǎn)型多態(tài)寫法左父右子是正常的向上轉(zhuǎn)型
4.向下轉(zhuǎn)型:為了讓對象調(diào)用子類方法(向上轉(zhuǎn)型只能調(diào)用左邊編譯類型的父類方法)
左子類右父類,是一個還原的過程,將父類對象還原成子類對象,且不能向下轉(zhuǎn)成別的子類。
格式: 子類名 對象名 = (子類名) 父類對象名; (后者也可以是接口)
Fu fu = new Fu();//向上轉(zhuǎn)型創(chuàng)建父類對象
Zi two = (Zi) one;//將父類對象還原成子類對象。
5.強(qiáng)制向下轉(zhuǎn)型時,判斷前面的對象是否是后面類型的實例,是否可以成功轉(zhuǎn)換,從而保證代碼更加健壯。
格式: 對象 instanceof 類型
得到一個boolean值結(jié)果(true/false),判斷前面的對象能否作為后面類型的實例
Zi two = (Zi) one;//將父類對象還原成子類對象。
System.out.println(one instanceof Fu);//輸出true,one可以做Fu類的實例對象
System.out.println(one instanceof Zi);//輸出true,one可以做Zi類的實例對象
三、接口
1.接口定義了某一批類需要遵守的規(guī)范。這就意味著接口里通常是定義一組公用方法。
2.接口是一種引用數(shù)據(jù)類型(類、接口、數(shù)組),注意其中的抽象方法。
3.接口可以繼承接口,但不能繼承類。
4.Java9 里可以有常量、抽象方法、默認(rèn)方法、靜態(tài)方法、私有方法。
5.備注:接口編譯后生成的同樣是.class的字節(jié)碼文件
//格式
public interface 接口名稱(首字母大寫){
//抽象方法
}
- 接口里的成員變量只能是常量,必須用public static final修飾,可省略
//final即為不可改變
public static final int MAX_NUMBER = 20;
- 接口里的[普通方法]只能是抽象方法,public abstract可以省略
public abstract void out();
void getDate();
- 接口中的[默認(rèn)方法]需要用default修飾
/*
當(dāng)接口新添加方法時,新方法寫為默認(rèn)方法,則可以不去動其實現(xiàn)類,默認(rèn)方法自動被其繼承
默認(rèn)方法同樣可以被覆寫。
*/
public default void print() {
foo();
System.out.println("默認(rèn)方法調(diào)用3");
}
- 接口中定義[靜態(tài)方法],需要用static修飾
public static void staticTest() {
System.out.println("靜態(tài)方法!");
}
- 當(dāng)倆默認(rèn)方法中有重復(fù)內(nèi)容時,抽取出來定義私有方法
//定義私有默認(rèn)方法,給默認(rèn)方法調(diào)用,但不應(yīng)被實現(xiàn)類使用,所以權(quán)限為私有
private void foo() {
System.out.println("默認(rèn)方法調(diào)用2");
}
//定義私有靜態(tài)方法,給靜態(tài)方法調(diào)用,但不應(yīng)被實現(xiàn)類使用,所以權(quán)限為私有
private static void bar() {
System.out.println("bar私有靜態(tài)方法");
}
}
- 接口不能創(chuàng)建實例,但能用于聲明引用類型變量,且必須引用到實現(xiàn)類的對象;
- 一個實現(xiàn)類可以同時實現(xiàn)多個接口
//格式:
.public class 實現(xiàn)類名稱 impliments{
//必須覆寫接口中所有抽象方法;
},
- 在實現(xiàn)類(impliments)中進(jìn)行接口的實現(xiàn):
//
public class Demo01InterfaceImpl implements Demo01Interface,Demo02Interface {
//1,2接口都有out抽象方法,但只需覆寫一次
@Override
public void out() {
System.out.println("抽象方法覆寫!");
}
@Override
public void getDate() {
System.out.println("抽象方法覆寫!");
}
@Override
public void print(){
System.out.println("沖突的默認(rèn)方法也需要覆寫!");//不沖突則不用覆寫
}
}
- 然后在main類里創(chuàng)建實現(xiàn)類的對象,進(jìn)行調(diào)用
public class Impliments {
public static void main(String[] args) {
//創(chuàng)建實現(xiàn)類的對象
Demo01InterfaceImpl ImplementationObject1 = new Demo01InterfaceImpl();
ImplementationObject1.getDate();
ImplementationObject1.out();
ImplementationObject1.print();//調(diào)用實現(xiàn)類里繼承自接口的默認(rèn)方法。
//接口里的靜態(tài)方法只能通過接口名稱直接調(diào)用。
Demo01Interface.staticTest();
//通過接口名直接訪問常量。
System.out.println(Demo01Interface.MAX_NUMBER);
}
}
- 接口是多繼承,一個接口可以有多個父接口。
- 多個父接口中的抽象方法如果存在重名,正常覆寫;但默認(rèn)方法重名需要帶有default關(guān)鍵字覆寫。
- 正常不沖突抽象方法不需要再覆寫(實現(xiàn)類多個接口時也是如此)。
//接口的多繼承,同樣使用extends關(guān)鍵字
public interface Demo03InterfaceExtends extends Demo01Interface,Demo02Interface {
@Override
default void print() {
//覆寫父接口的默認(rèn)方法不能省略default關(guān)鍵字
}
}
四、抽象類
- 抽象方法:加上abstract關(guān)鍵字,去掉大括號,直接分號結(jié)束;
- 抽象類:抽象方法所在的類必須是抽象類,再class之前寫上abstract即可
- 不能直接new抽象類對象,必須用一個子類來繼承抽象父類
(抽象類對象調(diào)用的方法存在沒有具體內(nèi)容的方法體,因此沒有意義) - 創(chuàng)建子類對象,不可創(chuàng)建抽象父類對象;
public abstract class demo01Abstract {
public abstract void method1();
public abstract void method2();
}
- 子類必須覆寫抽象類中的所有抽象方法(去掉abstrat,補上大括號)。
(假設(shè)不全部覆寫,對象調(diào)用的方法存在抽象方法,沒有意義)
//使用extends繼承抽象父類
public abstract class demo02Zi extends demo01Abstract {
//只覆寫了一個抽象方法,沒有將抽象方法全部覆寫完,也就是說本子類還存在著繼承下來的未覆寫的抽象方法
//所以該類也同樣是抽象類
@Override
public void method1() {
System.out.println("已經(jīng)覆寫第method1方法!");
}
}
//在這個子子類中已經(jīng)將所有抽象方法全部覆寫,所以該類不再是抽象類!
public class demo03Sun extends demo02Zi {
@Override
public void method2() {
System.out.println("已經(jīng)覆寫method2方法!");
}
}
- 最后在main類中的main方法里創(chuàng)建對象進(jìn)行調(diào)用即可。
五、final關(guān)鍵字
- final表示它修飾的類、方法、成員變量、局部變量不可改變。
- final修飾的類不可被繼承下去。無子類,不可被覆蓋重寫。
public final class 類名(){}
- final修飾的方法不可被覆蓋重寫。
public final void method(){}
- 類和方法不能同時使用final和abstract,二者矛盾。abstract表示抽象,是待定的;final表示最終的,是確定的。
- final修飾局部變量,若是基本數(shù)據(jù)類型的數(shù)值,則不可改變;若是引用數(shù)據(jù)類型,則地址值不可改變,但地址指向的對象的內(nèi)容可以改變。
- final修飾成員變量,也不可變,但必須要進(jìn)行手動賦值,成員變量加final后不允許再擁有默認(rèn)值。
public final class Demo01Final {
public static void main(String[] args) {
int NUM = 1;
System.out.println(NUM);
NUM = 2;//可以改變
System.out.println(NUM);
final int NUM1 = 2;
// NUM1 = 3; 錯誤,NUM是確定的值,不可被改變。
}
}
六、權(quán)限修飾符
- 權(quán)限大小:
四種權(quán)限修飾符,訪問權(quán)限從大到小:
public > protected > 空 > private
同一個類: yes yes yes yes
同一個包: yes yes yes no
不同包子類: yes yes no no
不同包非子類:yes no no no
在這里插入圖片描述
七、內(nèi)部類
一個外部類包含的一個嵌套的類,叫內(nèi)部類。
分類:
1.成員內(nèi)部類。
2.局部內(nèi)部類(包含匿名內(nèi)部類)。
- 注意:內(nèi)部類可以無限制地訪問外部類,外部類訪問內(nèi)部類需要內(nèi)部類對象。
- 各個類對應(yīng)可以使用的權(quán)限修飾符如下:
外部類:public/(default)
成員內(nèi)部類:public.protect.(default).private
局部內(nèi)部類:什么都沒有,注意并不是(default) - 內(nèi)部類定義示例:
public class main {
private String name = "成員變量";
//定義一個成員內(nèi)部類
public class innerClass {
private String innername = "內(nèi)部成員變量";
}
// 定義一個成員內(nèi)部類內(nèi)的成員方法
public void innermethod1() {
System.out.println("內(nèi)部類方法");
System.out.println(name);
}
}
使用內(nèi)部類的兩種方式:
1.直接:在main方法中創(chuàng)建內(nèi)部類對象:格式:
外.內(nèi) = new 外().內(nèi)();
外部類名稱.內(nèi)部類名稱 對象名 = new 外部類名稱().new 內(nèi)部類名稱();
public static void main(String[] args) {
//直接創(chuàng)建內(nèi)部類的對象。
InnerclassUsing.innerClass object = new InnerclassUsing().new innerClass();
object.innermethod1();
}
2.間接:在外部類的方法中,只用內(nèi)部類,main只是調(diào)用外部類的方法,通過外部類方法訪問內(nèi)部類。
public class InnerclassUsing {
private String name = "成員變量";
//定義一個成員內(nèi)部類
public class innerClass {
private String innername = "內(nèi)部成員變量";
// 定義一個成員內(nèi)部類的成員方法
public void innermethod1() {
System.out.println("內(nèi)部類方法");
System.out.println(name);
}
}
public void outMethod() {
System.out.println("外部類成員方法");
// System.out.println(innername); 錯誤。
//通過匿名對象訪問內(nèi)部類變量和方法
System.out.println(new innerClass().innername);
//創(chuàng)建匿名對象并調(diào)用innermethod1方法。
new innerClass().innermethod1();
}
}
內(nèi)部類的重名變量訪問格式:
- 本方法: 空
- 本類成員變量:this.
- 外部類成員變量:外部類的名稱.this.
public class Demo03CommonName {
//外部類成員變量
int NAME = 1;
public class innerClass{
//內(nèi)部類成員變量
int NAME = 2;
public void method (){
//內(nèi)部類局部變量
int NAME = 3;
System.out.println(NAME);//3,局部變量,就近原則。
System.out.println(this.NAME);//2,本類成員變量。
System.out.println(Demo03CommonName.this.NAME);//1,外部類的成員變量;
}
}
}
如果一個類定義在方法內(nèi)部,那么這個類叫局部內(nèi)部類。
局部內(nèi)部類只能被當(dāng)前所屬的方法所使用,外部不可。
格式:
public class Localinnerclass {
String NAME = "外部成員變量";
public void method(){
//定義局部內(nèi)部類
class localLinnerClass{
String ONE = "局部內(nèi)部類成員變量";
public void nmethod2(){
System.out.println("局部內(nèi)部類的成員方法");
System.out.println(ONE);
}
}
}
}
局部內(nèi)部類,如果希望訪問所在方法的局部變量,該變量應(yīng)該滿足【有效final】的條件
public class Demo04Final {
public void method1(){
//這里即使不寫final的話,不去修改 也算是有效final [從java8開始]
final String NAME = "bilibili";
class LocalInnerclass{
public void localInnerMethod(){
//局部內(nèi)部類內(nèi)的方法訪問所在類外部的方法的局部變量
System.out.println(NAME);
}
}
}
}
當(dāng)接口是實現(xiàn)類只使用唯一一次時,可以使用匿名內(nèi)部類
- 格式
接口名稱 對象名 = new 接口名稱(){
//這里進(jìn)行抽象方法的覆寫。
}; //別忘了結(jié)尾的分號
匿名內(nèi)部類在創(chuàng)建對象的時候,只能使用唯一一次
匿名對象在使用方法時,只能使用唯一一次
匿名內(nèi)部類是省略了(實現(xiàn)類/子類名稱),而匿名對象則是省略了對象名稱,二者不同。
//當(dāng)實現(xiàn)類只使用一次時,可以使用匿名內(nèi)部類的寫法!
Anonymous obj6 = new Anonymous() {
//覆寫匿名內(nèi)部類里所有抽象方法!
@Override
public void method1() {
System.out.println("bilibili?");
}
@Override
public void method2(){
System.out.println("覆寫method!");
}
};
obj6.method1();//打印內(nèi)容
obj6.method2();
將類作為成員變量的寫法
//定義一個武器類
public class Weapon {
private String itsname;//武器名稱
private int attacknum;//武器攻擊力
//無參構(gòu)造方法
public Weapon() {
}
//全參方法
public Weapon(String itsname, int attacknum) {
this.itsname = itsname;
this.attacknum = attacknum;
}
//get名字
public String getItsname() {
return itsname;
}
//set名字
public void setItsname(String itsname) {
this.itsname = itsname;
}
//get攻擊力
public int getAttacknum() {
return attacknum;
}
//set攻擊力
public void setAttacknum(int attacknum) {
this.attacknum = attacknum;
}
}
//定義一個女武神類
public class Valkyrie1 {
private String name;//女武神之名
private Weapon weapon;//將武器類變?yōu)槌蓡T變量 交給女武神類
//女武神攻擊方法
public void attack(){
System.out.println(name + "使用的" + weapon.getItsname() + "具有" + weapon.getAttacknum() +"點攻擊力");
}
//無參構(gòu)造
public Valkyrie1() {};
//全參
public Valkyrie1(String name, Weapon weapon) {
this.name = name;
this.weapon = weapon;
}
//get女武神名字
public String getName() {
return name;
}
//set女武神名字
public void setName(String name) {
this.name = name;
}
//get女武神武器
public Weapon getWeapon() {
return weapon;
}
//set女武神武器
public void setWeapon(Weapon weapon) {
this.weapon = weapon;
}
}
- 定義了女武神類和武器類后,在main方法中進(jìn)行調(diào)用
Valkyrie1 valkyrie = new Valkyrie1();//創(chuàng)建一個女武神
valkyrie.setName("bronya"); //set女武神名字叫bronya
Weapon weapon = new Weapon("真理之鑰",1000);//創(chuàng)建一把武器,并同時賦予名稱和攻擊力
// 也可以分開寫: weapon.setItsname("真理之鑰");//武器名字
// 也可以分開寫: weapon.setAttacknum(1000);//武器攻擊力
valkyrie.setWeapon(weapon);//將定義好的武器交給女武神
valkyrie.attack();//最后,女武神使用這把武器進(jìn)行攻擊
**
- 關(guān)注我,一起學(xué)習(xí)、一起進(jìn)步,無限期更新,期待下一期哦!
- 關(guān)注微信公眾號 崩天的勾玉 回復(fù) java 免費領(lǐng)取視頻學(xué)習(xí)資料
- Bye!