Java學習 DAY10 抽象類、介面、內部類

2020-08-14 19:09:37

abstract(抽象)

關鍵字,修飾符 方法、類

當所有的子類對父類別的某個方法都進行了不同程度的重寫,那麼這個方法的方法體沒有實際含義就可以把方法體去掉,加上abstract關鍵字修飾方法-----抽象方法。一個類中如果出現了抽象方法那麼這個類就要變成抽象類。普通類繼承抽象類需要重寫所有的抽象方法,如果不想重寫所有的抽象方法可以把普通類變成抽象類。

package cn.tedu.abstractx;

public class AbstractDeno1 {
    public static void main(String[] args) {
        //物件是匿名內部類的物件
        TuXing t = new TuXing(1,2) {
            @Override
            public double getGirth() {
                return 0;
            }
        };//匿名內部類
    }

}



//圖形類
//當類中出現抽象方法時類要變成抽象類
abstract class TuXing{
    //定義私有屬性
    private double a;
    private double b;

    //有參構造---通過有參構造給私有化屬性進行賦值
    public  TuXing(double a,double b){
        this.a = a;
        this.b = b;

    }

    //提供get方法間接獲取私有化屬性值
    public double getA() {
        return a;
    }

    public double getB() {
        return b;
    }
    //提供周長面積計算方法
    //抽象方法---1.沒有方法體  2.一定要重寫
    public abstract double getGirth();
    //public abstract double getGirth(int m);
    /*{
        return 0.0;//因爲沒有確切圖形不能使用具體計算公式
    }*/
    /*//普通方法----實體方法
    public double getArea(){
        return 0.0;//因爲沒有確切圖形不能使用具體計算公式
    }*/
}


//矩形類
//當普通類繼承抽象方法需要重寫所有的抽象方法
//如果普通類不想重寫抽象類中所有的抽象方法可以變爲抽象類
abstract class JuXing extends TuXing{

    //有參構造---呼叫父類別有參構造給父類別私有化屬性間接賦值
    public  JuXing(double a,double b){
        super(a,b);
    }

    //重寫周長面積計算方法
    /*public double getGirth(){
        return 2*(getA()+getB());//求周長
    }*/
    public double getArea(){
        return getA()*getB();//求面積
    }
}

//正方形類
class ZhengFang extends JuXing{
    //有參構造--呼叫父類別有參構造給父類別私有化屬性間接賦值
    public  ZhengFang(double a){
        super(a,a);
    }
    //重寫周長面積計算方法
    public double getGirth(){
        return 2*(getA()+getB());//求周長
    }
}

//圓形類
class Yuan extends TuXing{
    //有參構造--呼叫父類別有參構造給父類別私有化屬性間接賦值
    public Yuan(double r) {
        super(r, r);
    }
    //重寫周長面積計算方法
    public double getGirth(){
        return 3.14*2*getA();//求周長
    }
    public double getArea(){
        return getA()*getA()*3.14;//求面積
    }
}

注意:
1.抽象方法可以過載?可以
2.抽象類裡一定含有抽象方法?不一定
3.抽象類中可以定義屬性以及普通方法?可以
4.抽象類可以定義構造方法?可以
5.抽象方法可以建立物件?抽象類沒有物件
6.抽象方法可以被private/static/final單獨修飾?不可以 因爲抽象方法一定重寫
7.抽象類可以被final修飾?不可以 最終類不能被繼承
8.抽象類目的就是爲了延展類的繼承結構

interface(介面)

當抽象類中所有的方法都是抽象方法時,把抽象類變成介面來表示(用interface)。介面本質不是一個類,類和介面之間通過implements產生關聯關係—實現。Java支援介面與介面只減多繼承,類與介面之間多實現,就是爲了實現類能具有更多豐富的功能。實現類需要重寫介面所有的抽象方法,但是如果不想都重寫需要把實現類變成抽象類。

package cn.tedu.interfacex;

import java.io.Serializable;

public class InterfaceDemo1 {
    public static void main(String[] args) {
        System.out.println(Shape.i);
    }
}


//代表圖形的類
//當抽象類裡都是抽象方法時可以把類轉成介面來表示
//介面本質不是類
//介面與介面之間支援多繼承
interface Shape extends Cloneable, Serializable {
    //屬性,預設被public final static共同修飾
    public final static int i = 1;
    //抽象方法預設被public abstract修飾
    public abstract double getGirth();
    public abstract double getArea();
}


//代表矩形---普通類
//implements---代表類與介面之間的實現關係
//實現類
//類與介面之間支援多實現
//實現類需要把介面裏的所有抽象方法進行重寫,如果不想都重寫可以把實現類變爲抽象類
abstract class Rectangle implements Shape , Cloneable{
   /* @Override
    public double getGirth() {
        return 0;
    }*/
    @Override
    public double getArea() {
        return 0;
    }
}


package cn.tedu.interfacex;
public class InterfaceDemo2 {
    public static void main(String[] args) {
        //向上造型
        B b=new C();

        //編譯和執行都沒問題
        //在做物件賦值時編譯時期和執行時期都會有對應的檢測
        //在編譯時期會檢測兩個物件的宣告類是否有繼承關係
        //c物件的宣告類是C類,b物件的宣告類是B類,此時有繼承關係則編譯通過
        //在執行時期檢測兩個物件的實際建立類是否一致
        //c物件實際建立類是C類,b物件實際建立類是C類,此時一致執行通過
        C c=(C)b;//向下造型

        //ClassCastException---型別轉換異常
        //編譯沒有問題,執行有問題
        //在編譯時期d物件宣告類是D類,b物件的宣告類是B類,有繼承關係則編譯通過
        //在執行期間d物件的實際建立類是D類,b物件的實際建立類是C類不一致執行報錯
        //D d=(D)b;

        //編譯有問題
        //在編譯時期d物件宣告類是D類,c物件的宣告類是C類此時沒有繼承關係則編譯錯誤
        //d=(D)c;

        //類與類之間單繼承(樹狀圖)可以快速確定兩者之間的關係,編譯時期會有對應的檢測
        //類與介面之間是多實現(網狀圖)在確定兩者關係時需要耗費大量的資源,編譯時期沒有檢測
        //但是在執行時期仍然有檢測,檢測實際建立類是否是介面的實現類。
        A a=(A)b;
        A a1=(A)c;

        //
        System.out.println("over~");

    }
}
interface A{}
//C類和D類稱之爲同類
class B{}
class C extends B{}
class D extends B{}

注意:
1.介面裏的方法都是抽象方法?介面裏的方法都是抽象方法(和版本有關係)
2.介面裏可以定義構造方法?不能
3.介面可以建立物件?不能
4.介面裏可以定義屬性?可以定義,屬性預設被public final static共同修飾,抽象方法預設被public abstract共同修飾
5.介面宣告物件在編譯時期可以接收所有物件的型別物件的賦值,但是在執行時期檢測物件實際建立類是否是介面的實現類
6.介面的目的是讓實現類注入更多的特性

抽象類與介面的區別
1.介面不是類
2.介面裏面只有抽象方法
3.類與介面支援多實現,介面與介面支援多繼承
4.介面裏屬性和抽象方法有預設修飾符
5.抽象類有構造方法
6.抽象類爲了延展類的繼承結構,介面是爲了注入更多的特性

介面優點
模板、約束

內部類

類/介面裏定義類
類裡定義類

***方法內部類******
 在方法內定義類
 可以定義所有的非靜態資訊以及靜態常數
 可以正常的繼承和實現
 不能被存取許可權修飾符來修飾但是可以被abstract以及final來修飾
 可以獲取外部類所有的資訊
 只能獲取當前方法的常數資訊
package cn.tedu.inner;

public class InnerDemo1 {
    public static void main(String[] args) {
        //建立外部類物件呼叫方法執行建立內部類物件的語句
        new Outer1().m();
    }
}

//外部類
class Outer1{
    //屬性
    int k=1;
    //方法
    public void m(){
        int y=1;//在jdk1.8以前定義常數需要手動加上final
                //在jdk1.8及其以後定義變數時底層預設會新增final但是如果手動新增了
                //底層就不再新增
        y=3;

        //方法內部類
        //定義所有非靜態資訊以及靜態常數
        //可以正常的繼承與實現
        //不能被存取許可權修飾符來修飾但是可以被abstract以及final來修飾
        //可以獲取外部類所有資訊
        //只能獲取本方法的常數

        class Inner1 extends Object implements Cloneable{
            static final int x=1;
            public void n(){
                System.out.println(k);
                //System.out.println(y);
            }
        }
        System.out.println(y=5);
        //建立方法內部類
        Inner1 in1=new Inner1();
        in1.n();
    }
}

成員內部類
在成員位置定義類
可以定義所有的非靜態資訊以及靜態常數
可以正常的繼承和實現
可以被存取許可權修飾符以及abstract以及final來修飾
可以獲取外部類所有的資訊

package cn.tedu.inner;

import java.util.Scanner;

public class InnerDemo2 {
    public static void main(String[] args) {
        //Outer2.Inner2表示內部類
        // Outer2.Inner2 inner2=new Outer2().in2;
        //in2 = newInner2();
        Outer2.Inner2 inner2=new Outer2().new Inner2();
    }
}

//外部類
class Outer2{
    //屬性
    int k=1;

    //非靜態屬性
    //Inner2 in2 = new Inner2();

    //成員內部類
    //可以定義所有非靜態資訊以及靜態常數
    //可以正常的繼承和實現
    //可以讓存取許可權修飾符以及abstract和final來修飾
    //可以獲取外部類所有的資訊
    final class Inner2 extends Object implements Cloneable{
        static final int x=1;
        public void n(){
            System.out.println(k);
            m();
        }

    }

    //方法
    public void m(){}

}

靜態內部類
在成員內部類被static修飾
可以定義所有資訊
可以正常的繼承和實現
可以被存取許可權修飾符以及abstract以及final來修飾
可以獲取外部類的靜態資訊

package cn.tedu.inner;

public class InnerDemo3 {
    public static void main(String[] args) {
        //建立靜態內部類物件
        Outer3.Inner3 inner3 = new Outer3.Inner3();

    }
}


//外部類
class  Outer3{
    //屬性
    static int k = 1;

    //
    static  Inner3 in3=new Inner3();

    //靜態內部類
    //static修飾的類一定是內部類
    //可以定義所有資訊
    //可以進行正常的繼承和實現
    //可以被存取許可權修飾符以及abstract和final修飾
    //只能獲取外部類靜態資訊
     static class Inner3 extends Object implements Cloneable{
        static int x=1;
        public void n(){
            System.out.println(k);
        }
    }

    //方法
    public void m(){}
}

    匿名內部類
       用於繼承類/實現介面,重寫抽象方法
       可以被繼承的類/介面都可以擁有匿名內部類的形式
       匿名內部類只能使用一次
       當做參數傳遞時來使用
package cn.tedu.inner;

public class InnerDemo4 {
    public static void main(String[] args) {
        //建立抽象類子類物件
        /*D d=new D();
        d.m();*/

        //匿名內部類
        //繼承類,重寫抽象方法,建立匿名內部類物件
        //當類可以被繼承/是介面時,擁有匿名內部類的形式
        //只能使用一次
        C c=new C(){
            @Override
            public void m() {
                System.out.println(1);
            }
        };
        c.m();
        //普通類也具有匿名內部類的形式
        B b=new B(){};

        //介面也具有匿名內部類的形式
        A a=new A() {
        };

        //呼叫方法
        //當作參數使用
        m(new A(){});
    }
    //
    public static void m(A a){//只能接收A介面的實現類物件

    }

}

//介面
interface A{}

//普通類
class B{}

//
abstract class C{
    public abstract void m();
}


class D extends C{
    @Override
    public void m() {
        System.out.println(1);
    }
}

介面裏定義類/內部介面預設都是被static修飾

package cn.tedu.inner;

public class InnerDemo5 {
    public static void main(String[] args) {
        System.out.println(Outer5.Inner5.i);
        System.out.println(Outer5.Inner6.j);
        System.out.println(Outer5.Inner5.Inner7.x);
    }
}

interface Outer5{

    //介面裏定義介面,預設被static修飾
    interface Inner6{
        int j=1;
    }

    //介面裏定義內部類預設被static修飾
    static class Inner5{
        static int i =1;

        //類裡定義介面,預設被static修飾
        static interface Inner7{
             int x=1;
        }
    }
}