Java 內部類(成員內部類、局部內部類、靜態內部類,匿名內部類)


一、什么是內部類?

  內部類是指在一個外部類的內部再定義一個類。內部類作為外部類的一個成員,並且依附於外部類而存在的。內部類可為靜態,可用protected和private修飾(而外部類只能使用public和缺省的包訪問權限)。

   內部類主要有一下幾種:成員內部類、局部內部類、靜態內部類、匿名內部類

二、內部類的共性:

(1)、內部類仍然是一個獨立的類,在編譯之后內部類會被編譯成獨立的.class文件,但是前面冠以外部類的類名和$符號 。

(2)、內部類不能用普通的方式訪問。

(3)、內部類聲明成靜態的,就不能隨便的訪問外部類的成員變量了,此時內部類只能訪問外部類的靜態成員變量 。

(4)、外部類不能直接訪問內部類的的成員,但可以通過內部類對象來訪問

 

三、為什么需要內部類?

其主要原因有以下幾點:

  1、內部類方法可以訪問該類定義所在的作用域的數據,包括私有的數據

  2、內部類可以對同一個包中的其他類隱藏起來,一般的非內部類,是不允許有 private 與protected權限的,但內部類可以

  3、可以實現多重繼承

  4、當想要定義一個回調函數且不想編寫大量代碼時,使用匿名內部類比較便捷

使用內部類最吸引人的原因是:

  每個內部類都能獨立地繼承自一個(接口的)實現,所以無論外圍類是否已經繼承了某個(接口的)實現,對於內部類都沒有影響。大家都知道Java只能繼承一個類,它的多重繼承在我們沒有學習內部類之前是用接口來實現的。但使用接口有時候有很多不方便的地方。比如我們實現一個接口就必須實現它里面的所有方法。而有了內部類就不一樣了。它可以使我們的類繼承多個具體類或抽象類。

四、代碼實現

  1、成員內部類

即在一個類中直接定義的內部類,成員內部類與普通類的成員沒什么區別,可以與普通成員一樣進行修飾和限制。成員內部類不能含有static的變量和方法。

package com.test;

public class Outer {
    private static int number = 100;
    private int j = 20;
    private String name = "Java";

    public static void outer_funOne(){
        System.out.println("外部類Outer的靜態方法:outer_funOne");
    }

    public void outer_funTwo(){
        System.out.println("外部類的普通方法:outer_funTwo");
    }

    //成員內部類,可以訪問外部類的所有成員
    class Demo{
        //內部類不允許定義靜態變量
        //static int demo_i = 100;
        int j =50; //內部類和外部類的實例變量可以共存

        //成員內部類中的方法定義
        public void demo_funOne(){
            //內部類中訪問內部類自己的變量直接用變量名
            //也可以用  this.j
            System.out.println(j);

            //內部類中訪問外部類的成員變量語法:外部類類名.this.變量名
            System.out.println("內部類訪問外部類變量:"+Outer.this.j);

            //如果內部類中沒有與外部類中有相同的變量,則可以直接用變量名使用
            System.out.println(name);

            //內部類調用外部類方法
            outer_funOne();  //靜態方法
            outer_funTwo();  //非靜態方法

        }

    }


    public static void outer_funThree(){
        //外部類靜態方法訪問成員內部類
        // 1、建立外部類對象
        Outer out = new Outer();
        //  2、根據外部類建立內部類對象
        Demo demo = out.new Demo();
        // 訪問內部類方法
        demo.demo_funOne();
        //訪問內部類字段
        System.out.println("內部類成員字段:"+demo.j);
    }

    public static void main(String[] args) {
        //調用內部類的方法
        // 1、創建外部類對象
        Outer out = new Outer();
        // 2、通過外部類對象創建內部類對象
        Outer.Demo demo = out.new Demo();

        // 1、2步簡寫
        // Outer.Demo demo1 = new Outer().new Demo();

        //方法調用
        demo.demo_funOne();

    }

}

結果:

  2、局部內部類

    在方法中定義的內部類稱為局部內部類。與局部變量類似,局部內部類不能有訪問說明符,因為它不是外圍類的一部分,但是它可以訪問當前代碼塊內的常量,和此外圍類所有的成員。

需要注意的是:

  (1)、局部內部類只能在定義該內部類的方法內實例化,不可以在此方法外對其實例化。

  (2)、局部內部類對象不能使用該內部類所在方法的非final局部變量。

 

package com.test;

public class Outer {
    private static int number = 100;
    private int j = 20;
    private String name = "Java";

    //定義外部類方法
    public void outer_funOne(int k){
        final int number = 100;
        int j = 50;

        //方法內部的類(局部內部類)
        class Demo{
            public Demo(int k){
                demo_funOne(k);
            }

            int number = 300; //可以定義與外部類同名的變量
            // static int j = 10;  //不可以定義靜態變量

            //內部類的方法
            public void demo_funOne(int k){
                System.out.println("內部類方法:demo_funOne");
                //訪問外部類的變量,如果沒有與內部類同名的變量,則可直接用變量名
                System.out.println(name);
                //訪問外部類與內部類同名的變量
                System.out.println(Outer.this.number);
                System.out.println("內部類方法傳入的參數是:"+k);
            }
        }

        new Demo(k);
    }




    public static void main(String[] args) {
        //訪問內部類必須要先有外部類對象
        Outer out = new Outer();
        out.outer_funOne(11);
    }

}

 

 

 結果:

  3、靜態內部類(嵌套類)

  如果你不需要內部類對象與其外圍類對象之間有聯系,那你可以將內部類聲明為static。這通常稱為嵌套類(nested class)。想要理解static應用於內部類時的含義,你就必須記住,普通的內部類對象隱含地保存了一個引用,指向創建它的外圍類對象。然而,當內部類是static的時,就不是這樣了。嵌套類意味着:

  1. 要創建嵌套類的對象,並不需要其外圍類的對象。

  2. 不能從嵌套類的對象中訪問非靜態的外圍類對象。

 

package com.test;

public class Outer {
    private static int number = 100;
    private int j = 20;
    private String name = "Java";

    public static void outer_funOne(){
        System.out.println("外部類靜態方法:outer_funOne");
    }

    public void outer_funTwo(){

    }

    //靜態內部類可以用public、protected、private修飾
    //靜態內部類可以定義靜態類或非靜態內部類
    private static class Demo{
        static int j = 100;
        String name = "C#";

        //靜態內部類里的靜態方法
        static void demo_funOne(){
            //靜態內部類只能訪問外部類的靜態成員(靜態變量、靜態方法)
            System.out.println("靜態內部類訪問外部類靜態變量:"+number);
            outer_funOne();//訪問外部類靜態方法

        }

        //靜態內部類非靜態方法
        void demo_funTwo(){

        }

    }

    public void outer_funThree(){
        //外部類訪問內部類靜態成員:內部類.靜態成員
        System.out.println(Demo.j);
        //訪問靜態方法
        Demo.demo_funOne();
        //訪問靜態內部類的非靜態成員,實例化內部類即可
        Demo demo = new Demo();
        //訪問非靜態變量
        System.out.println(demo.name);
        //訪問非靜態方法
        demo.demo_funTwo();

    }


    public static void main(String[] args) {
        new Outer().outer_funThree();
    }

}

 

 

 結果:

  3、匿名內部類

簡單地說:匿名內部類就是沒有名字的內部類。什么情況下需要使用匿名內部類?如果滿足下面的一些條件,使用匿名內部類是比較合適的:

  1、只用到類的一個實例。

  2、類在定義后馬上用到。

  3、類非常小(SUN推薦是在4行代碼以下)

  4、給類命名並不會導致你的代碼更容易被理解。

在使用匿名內部類時,要記住以下幾個原則:
  1、 匿名內部類不能有構造方法。
  2、 匿名內部類不能定義任何靜態成員、方法和類。
  3、 匿名內部類不能是public,protected,private,static。
  4、 只能創建匿名內部類的一個實例。
  5、   一個匿名內部類一定是在new的后面,用其隱含實現一個接口或實現一個類。
  6、 因匿名內部類為局部內部類,所以局部內部類的所有限制都對其生效。

   代碼。。。。。。。。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM