Java基礎|內部類竟然有這些騷姿勢!(小白掃盲)

##內部類##
###內部類
在一個類中存在的其他類,叫做內部類。
###內部類作用

  1. 內部類可以很好的實現隱藏,對同一個包中的其他類不可見。一般的非內部類,是不允許有 private 與protected權限的,但內部類可以。

  2. 內部類擁有外圍類的所有元素的訪問權限。

  3. 使一個類間接實現多重繼承。

  4. 當定義一個回調函數,使用匿名內部類會使代碼變得簡潔(匿名內部類應實現接口或是繼承一個基類)。
    ###內部類原理
    內部類既可以訪問自身的數據域,也可以訪問創建它的外圍類對象的數據域。
    原理是:

  5. 內部類的對象有一個隱式的引用,它引用了實例化該內部對象的外圍類對象。對外圍類的引用在構造器中設置,編譯器修改了內部類的構造器,添加了外圍類引用參數。故可以訪問外圍類對象的所有屬性。

  6. 內部類是一種編譯器現象與虛擬機無關。

###內部類分類
局部內部類

  1. 定義在一個方法中的類,是局部內部類。不能用public或private聲明。作用域限定在聲明這個局部類的塊中。

  2. 局部內部類可訪問包含它的外部類,還可訪問這個塊中(局部類外)final屬性(即爲final的局部變量)。

匿名內部類

  1. 只創建一個類的對象,就不需要命名。匿名內部類無構造器,取而代之是將構造器參數傳遞給超類構造器;當匿名內部類實現接口的時候,無構造參數。
  2. 多用匿名內部類實現事件監聽器和其他回調。現推薦用lambda式。

靜態內部類

  1. 當使用內部類只是爲了把一個類隱藏在另外一個類的內部,並不需要內部類引用外圍類對象。可將內部類聲明爲static,以便取消產生的引用。
  2. 靜態內部類與常規內部類不同,靜態內部類可以有靜態域和方法。

###內部類間接多繼承用例
ClassA 基類

/**
 * @author gao tianci
 * @version $Id: ClassA.java, v 0.1 2017年7月23日 上午10:51:08 gao tianci Exp $
 */
public class ClassA {
    public void printA(String ags)
    {
        System.out.println("[ClassA]--printA()--ags:"+ags);
    }
}

ClassB 基類

/**
 * @author gao tianci
 * @version $Id: ClassB.java, v 0.1 2017年7月23日 上午10:51:25 gao tianci Exp $
 */
public class ClassB {
    public void printB(String ags)
    {
        System.out.println("[ClassB]--printB()--ags:"+ags);
    }
}

Printable 接口

/**
 * @author gao tianci
 * @version $Id: Printable.java, v 0.1 2017年7月23日 上午10:52:02 gao tianci Exp $
 */
public interface Printable {
    public void print();
}

ClassInner 類(間接多繼承)


/**
 * @author gao tianci
 * @version $Id: ClassInner.java, v 0.1 2017年7月23日 上午10:55:02 gao tianci Exp $
 */
public class ClassInner implements Printable {
    //外部類成員
    private String outerName = "outerName";
    private int    outerAge;
    public void pirntName() {
        System.out.println("[ClassInner]--outerName:" + outerName);
    }
    public void printAge() {
        System.out.println("[ClassInner]--outerAge:" + outerAge);
    }

    /**
     * 繼承ClassA
     * @author gao tianci
     * @version $Id: ClassInner.java, v 0.1 2017年7月23日 下午5:09:44 gao tianci Exp $
     */
    private class InnerClassA extends ClassA {
        //內部類使用外部類的成員
        private String innerAName = outerName;
        //內部類使用外部類的成員
        public void printInnerA() {
            print();
            pirntName();
            printAge();
            System.out.println("[outerName]:" + innerAName);
        }
        //內部類構造器
        public InnerClassA() {
            super();
        }
    }

    /**
     * 繼承ClassB,間接多繼承
     * @author gao tianci
     * @version $Id: ClassInner.java, v 0.1 2017年7月23日 下午5:09:48 gao tianci Exp $
     */
    public class InnerClassB extends ClassB {
        private String innerBName;
        public InnerClassB() {
            super();
        }
        //內部類構造器
        public InnerClassB(String innerBName) {
            super();
            this.innerBName = innerBName;
        }

        public String getInnerBName() {
            return innerBName;
        }
        public void setInnerBName(String innerBName) {
            this.innerBName = innerBName;
        }
    }

    /**
     * 獲取內部類實例方法
     * @return
     */
    public InnerClassA getInnerClassA() {
        return new InnerClassA();
    }

    /**
     * 獲取內部類實例方法
     * @return
     */
    public InnerClassB getInnerClassB() {
        return new InnerClassB();
    }

    /** 
     * @see com.ly.tainci.exercise.InnerClass.Printable#printable()
     */
    @Override
    public void print() {
        System.out.println("[Printable]--print()");
    }

    public String getOuterName() {
        return outerName;
    }

    public void setOuterName(String outerName) {
        this.outerName = outerName;
    }

    public int getOuterAge() {
        return outerAge;
    }

    public void setOuterAge(int outerAge) {
        this.outerAge = outerAge;
    }

    /**
     * 測試用例
     */
    @Test
    public void test() {
        //內部類測試用例
        InnerClassA innerClassA = this.getInnerClassA();
        innerClassA.printInnerA();
    }
}

TestCase 測試用例

/**
 * @author gao tianci
 * @version $Id: TestCase.java, v 0.1 2017年7月23日 上午10:51:34 gao tianci Exp $
 */
public class TestCase {
    @Test
    public void test() {
        ClassInner classInner = new ClassInner();
        classInner.setOuterName("outerName");
        classInner.setOuterAge(20);
        //繼承接口的方法
        System.out.println("----繼承接口的方法----");
        classInner.print();
        //外部類自己的成員方法
        System.out.println("----外部類成員方法----");
        classInner.printAge();
        classInner.pirntName();
        //創建內部類,方法一通過外部類對象創建,內部類修飾符是private則只能在它的外部類範圍使用
        InnerClassB innerClassB1 = classInner.new InnerClassB("innerBName1");
        //創建內部類,方法二在外部類中提供一個獲取內部類實例的方法,這種方式常推薦
        InnerClassB innerClassB2 = classInner.getInnerClassB();
        //內部類繼承它的父類方法
        System.out.println("----內部類繼承父類的方法----");
        innerClassB1.printB(innerClassB1.getInnerBName());
        innerClassB2.setInnerBName("innerClassB2");
        innerClassB2.printB(innerClassB2.getInnerBName());
        //內部類只能在它的內部獲取並使用它的外部類成員
        //innerClassB1.print();//錯誤
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章