1. 程式人生 > >JAVA之內部類

JAVA之內部類

        內部類是指在一個外部類的內部再定義的一個類,類名不需要和資料夾相同。

        內部類只是一個編譯時的概念,一旦編譯成功,就會成為完成不同的兩個類。所以內部類的成員變數或方法名可以和外部類相同。

原始碼:

public class Outer {
    private String  name;
    public static void main(String[] args) {
        Outer o = new Outer();
        o.setName("李四");
        o.print("hello");
        Inner in = o.getInner();
        in.setName("張三");
        in.print("你好");
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void print(String str){
        System.out.println(str+"   "+getName());
    }
    private Inner getInner(){
        return new Inner();
    }
    public  class Inner{
        private String name;
        public void print(String str){
            System.out.println(str+"   "+getName());
        }

        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
    }
}

編譯結果:


執行結果:

hello   李四
你好   張三

結果分析:

       根據編譯結果,我們發現生成了一個Outer.class和一個Outer$Inner.class檔案,證實內部類一旦編譯成功,就會成為兩個完全不同的類。內部類和外部類有相同的屬性和相同的方法。

       大概的梳理了一下什麼是內部類,下面按照成員內部類、區域性內部類、靜態巢狀類、匿名內部類四個方面進行詳細的闡述:

成員內部類:

       成員內部類是外圍類的一個成員,所以他可以訪問外圍類所有的屬性和方法(包括private),但是外圍類要訪問內部類的成員屬性和方法則需要通過內部類例項來訪問。

原始碼:

public class Outer {
    private String username;
    public void say(String str){
        System.out.println("Hello  " + str);
    }
    public class Inner {
        public void sayAge(int age) {
            System.out.println("我今年:" + age);
        }
        //呼叫外圍類的方法
        public void OuterFun() {
            username = "張三";
            say(username);
        }
    }
    public static void main(String[] args) {
        Outer out = new Outer();
        //第一種方式建立內部類物件,不支援使用
        Inner inner = out.new Inner();
        inner.sayAge(15);
        inner.OuterFun();

        //第二種方式建立內部類物件,推薦使用
        Inner inner1 = out.getInner();
        inner1.OuterFun();
    }
    public Inner getInner(){
        return  new Inner();
    }
}
程式碼解析:

       推薦使用Inner inner1 = out.getInner(); 建立內部類物件,因為內部類之所以定義在內部就是為了封裝,想要獲取內部類物件通常都通過外部類的方法來獲取。這樣可以對內部類物件進行控制。

注意:

       1、內部類定義在外部類成員位置上,可以使用一些成員修飾符修飾private,static。

       2、採用私有修飾符是因為封裝性不讓其他程式直接訪問,所以內部類通常都會被私有化。

       3、如果內部類被靜態修飾,就相當於外部類,並且只能訪問外部類的靜態成員。

       4、如果內部類中定義靜態成員,那麼該內部類必須是靜態的。

區域性內部類:

       區域性內部類,是巢狀在方法和作用域內的,對於這個類的使用主要是應用與解決比較複雜的問題,想建立一個類來輔助我們的解決方案,但是又不希望這個類是公共可用的,所以就產生了區域性內部類,區域性內部類和成員內部類一樣被編譯,只是他的作用域發生了改變,它只能在該方法和屬性中被使用,出了該方法和屬性就會失效。

       針對於區域性內部類,我就不展示案例了。因為我在專案開發中,從來還沒有使用過區域性內部類,我只是瞭解概念,看過《Think in Java》中的案例。如有大神對此很理解,望多多指導。

靜態巢狀類:

       在成員內部類的注意事項中我們提起內部類可以被靜態(static)修飾,修飾後相當於外部類,並且只能訪問外部類的靜態成員。其實靜態巢狀類就是在成員內部類上加上靜態(static)的修飾。

       靜態內部類和非靜態內部類中存在一個區別,非靜態內部類在編譯完成之後會隱含地儲存著一個引用,該引用是指向建立它的外部類的。但是靜態內部類卻沒有,代表這靜態內部類建立不需要依賴於外部類,他不能使用任何外部類的非static成員變數和方法。

案例:

public class StaticOuter {
    private  static String username;
    static class StaticInner{
        public StaticInner() {
            username = "張三";
        }
        public void  say(){
            System.out.println("Hello "+ username);
        }
    }
    public static void main(String[] args) {
        StaticInner inner = new StaticInner();
        inner.say();
    }
}

匿名內部類:

       匿名內部類,很容易理解。就是沒有名字的內部類,也是內部類的簡化形式。一般只用一次就可以用這種形式。匿名內部類其實就是一個匿名子類物件。想要定義匿名內部,內部類必須繼承一個類或者實現介面。

       匿名內部類的格式:new 父類名&介面名(){定義子類成員或覆蓋父類方法}.方法。

案例一:

public static void main(String[] args) {
        new IUserService(){
            @Override
            public void print(String str) {
                System.out.println("Hello  "+str);
            }
        }.print("王五");
    }

案例二:

public interface IUserService {
    void print(String str);
}

public class AnonymousInnerClass {
    public IUserService getUserService(){
        return  new IUserService() {
            @Override
            public void print(String str) {
                System.out.println("Hello " +str);
            }
        };
    }
    public static void main(String[] args) {
        AnonymousInnerClass innerClass = new AnonymousInnerClass();
        IUserService userService = innerClass.getUserService();
        userService.print("王五");

    }
}

       注:
  • 當函式的引數是介面型別引用時,如果介面中的方法不找過3個。可以通過匿名內部類完成引數的傳遞。
  • 在建立內部類時,建議該類中的封裝方法不要過多,最後是兩個或兩個以內。

總結 : 鞏固基礎,勇攀高峰!!!  加油!加油!加油!  ↖(^ω^)↗