內部類(成員內部類、局部內部類(包括匿名內部類))

這是我參與8月更文挑戰的第8天,活動詳情查看:8月更文挑戰java

一個事物的內部包含另外一個事物。一個類裏面包含另外一個類,這個類叫內部類,包含它的叫它外部類。markdown

例如:身體和心臟的關係;汽車和引擎的關係。ide

心臟、引擎只有在身體和汽車中才有用。內部類也同樣。post

分類:this

  1.成員內部類;spa

  2.局部內部類(包括匿名內部類);3d

1.成員內部類

/* 修飾符 class 外部類名稱{ 修飾符 class 內部類名稱{ ...... } ...... } */
public class Outer {
    private String name;

    public class Inter{
        public void InterMethod(){
            System.out.println("內部方法");
            System.out.println("姓名:" + name);   // 成員內部類能夠訪問外部類屬性
        }
    }
    public void fun1(){
        Inter in = new Inter();
        in.InterMethod();
    }
}
複製代碼

編譯後,這個類的class文件保存在磁盤裏code

內部類的使用方式

  在外部類中能夠直接經過 new 對象的方式使用。orm

  在其餘類中訪問:對象

    1.間接方式:在外部類的方法中使用內部類,而在其餘類中使用就 new 外部類調用這個方法;

/** * 其餘類使用內部類 */
public class OuterDemo1 {
    public static void main(String[] args) {
        Outer out = new Outer();
        out.fun1();
    }
}
複製代碼

    2.直接方式,直接建立出內部類

    公式: 外部類名稱.內部類名稱 對象名 = new 外部類名稱().new 內部類名稱();

public class OuterDemo2 {
    public static void main(String[] args) {
        Outer.Inter in = new Outer().new Inter();

        in.InterMethod();
    }
}
複製代碼

問題:在外部類、內部類、內部類方法體出現相同名稱屬性,如何輸出相應的值呢?

解決:

public class OuterDemo3 {

    private String name ="外";

    class Inter{
        private String name = "內";
        public void interMethod(){
            String name = "方法";
            System.out.println(name);   // 輸出: 方法,就近原則
            System.out.println(this.name);   // 輸出: 內
            System.out.println(OuterDemo3.this.name);    // 輸出: 外
        }
    }
}
複製代碼

2.局部內部類

  在方法體內定義一個類,出了這個方法,就沒法使用這個類(因此其餘類沒法使用【局部內部類】)

  普及:

  權限修飾符的使用規則:

  public > protected > (default) > private

  1.外部類:能使用 public / (defautl) 修飾

  2.成員內部類: public / protected / (default) / private

  3.局部內部類:什麼都不寫

public class Test {

    public void fun(){
        final int num = 100;
        class Fun{
            private void fun2(){
                System.out.println(num);
            }
        }
        Fun fun = new Fun();
        fun.fun2();
    }
}
複製代碼

問題:爲何訪問所在方法的局部變量,必需要有final修飾?

緣由(本質是生命週期問題)

  1.內部類 new 出來的對象在堆內存中;

  2.局部變量跟着方法,在棧內存中;

  3.方法運行完,馬上出棧,局部變量跟着消失;

  4.但 new 出來的對象,會在堆內存持續存在,直到垃圾回收;

  5.因此,要將該內存複製到常量池才能保存繼續使用。

3.匿名內部類(重要)

  往常,咱們要使用接口方法,得先定義該接口的實現類 -> 重寫該接口的全部抽象方法 -> new 實現類使用。

  而若是接口的實現類只是用惟一的一次,那麼這種狀況就能夠省略該實現類的定義,而改成使用 【匿名內部類】

接口

public interface MyInteface {
    void method();
}
複製代碼

使用【匿名內部類】

/** * 格式: * 接口名稱 對象名 = new 接口名稱(){ * // 覆蓋重寫全部抽象方法 * }; */
public class AnonymityTest2 {
    public static void main(String[] args) {
        MyInteface my = new MyInteface(){
            @Override
            public void method() {
                System.out.println("匿名內部類方法");
            }
        };
        my.method();
    }
}
複製代碼

  不少人一開始可能會有誤解:不是【匿名內部類】嗎? MyInteface my = new MyInteface(){...} 這不是有名字麼?

  先看,對於"new MyInteface(){...};" 的解析:

    1). new 表明對象建立的動做;

    2). 接口名稱 【匿名內部類】要實現的接口;

    3). {...} 這纔是【匿名內部類】的內容,裏面重寫着接口的全部抽象方法

  它光禿禿的,的確沒名沒姓的。

  而 MyInteface my = new MyInteface(){...} 中的 my 是對象名,它是供你調用匿名類方法的對象。

ps:匿名內部類、匿名對象

一、【匿名內部類】表示,在建立對象是,只能使用惟一一次,通常用於書寫接口的實現類。

    若是但願屢次建立對象,並且類的內容同樣的話,那仍是單獨定義實現類更方便。

public class AnonymityTest2 {
    public static void main(String[] args) {
        MyInteface my1 = new MyInteface(){
            @Override
            public void method() {
                System.out.println("匿名內部類方法");
            }
        };
        my1.method();
        MyInteface my2 = new MyInteface(){
            @Override
            public void method() {
                System.out.println("匿名內部類方法");
            }
        };
        my2.method();
    }
}
複製代碼

2.【匿名對象】表示,在調用方法時,只能調用惟一一次。

    若是但願同一對象,調用屢次方法,那麼仍是給對象起個名把。

new MyInteface(){
            @Override
            public void method1() {
                System.out.println("匿名內部類方法1");
            }

            @Override
            public void method2() {
                System.out.println("匿名內部類方法2");
            }
        }.method1();
        
        new MyInteface(){
            @Override
            public void method1() {
                System.out.println("匿名內部類方法1");
            }
            @Override
            public void method2() {
                System.out.println("匿名內部類方法2");
            }
        }.method2();
複製代碼

3.二者不是一回事

【匿名內部類】是省略了 <實現類 / 子類>

【匿名對象】是省略了 <對象名稱>

二者不是一回事。

public class AnonymityTest {
    public static void main(String[] args) {
        fun1();
    }

    private static void fun1() {
        // 對於 Thread 來講,這就是【匿名對象】
        // 對於 Runnable 來講,這就是【匿名內部類】
        new Thread( new Runnable(){
            @Override
            public void run() {

            }
        }).start();
    }
}
複製代碼
相關文章
相關標籤/搜索