Java基礎(chǔ)之內(nèi)部類

該項(xiàng)目源碼地址:https://github.com/ggb2312/JavaNotes/tree/master/java-basic

1. 簡(jiǎn)介

可以將一個(gè)類的定義放在另一個(gè)類的定義內(nèi)部,這就是內(nèi)部類键兜。

一般格式為:

public class Zoo{
    ...
    class Panda{
    }
}

內(nèi)部類是一種非常有用的特性位迂,它允許你把一些邏輯相關(guān)的類組織在一起伍伤,并控制位于內(nèi)部的類的可見性姻几。內(nèi)部類與組合是完全不同的概念必搞。

內(nèi)部類提供一種代碼隱藏機(jī)制:“將類置于其他類的內(nèi)部”绩脆,同時(shí)內(nèi)部類也了解外部類刘莹,并能與之通信。

2. 內(nèi)部類實(shí)例

內(nèi)部類有以下四種形式

  1. 成員內(nèi)部類
  2. 局部?jī)?nèi)部類
  3. 靜態(tài)內(nèi)部類
  4. 匿名內(nèi)部類

成員內(nèi)部類和靜態(tài)內(nèi)部類可以擁有private訪問(wèn)權(quán)限目代、protected訪問(wèn)權(quán)限屈梁、public訪問(wèn)權(quán)限及包訪問(wèn)權(quán)限嗤练。比如上面的例子,如果成員內(nèi)部類Inner用private修飾在讶,則只能在外部類的內(nèi)部訪問(wèn)煞抬,如果用public修飾,則任何地方都能訪問(wèn)构哺;如果用protected修飾此疹,則只能在同一個(gè)包下或者繼承外部類的情況下訪問(wèn);如果是默認(rèn)訪問(wèn)權(quán)限遮婶,則只能在同一個(gè)包下訪問(wèn)。這一點(diǎn)和外部類有一點(diǎn)不一樣湖笨,外部類只能被public和包訪問(wèn)兩種權(quán)限修飾旗扑。我個(gè)人是這么理解的,由于成員內(nèi)部類看起來(lái)像是外部類的一個(gè)成員慈省,所以可以像類的成員一樣擁有多種權(quán)限修飾臀防。

下面我們通過(guò)幾個(gè)實(shí)例來(lái)看看內(nèi)部類具體長(zhǎng)什么樣。

2.1 成員內(nèi)部類

成員內(nèi)部類和成員變量一樣边败,屬于類的全局成員袱衷。
成員內(nèi)部類可以擁有private訪問(wèn)權(quán)限、protected訪問(wèn)權(quán)限笑窜、public訪問(wèn)權(quán)限及包訪問(wèn)權(quán)限致燥。

一般格式:

public class OuterClass { //外部類
     int id; // 成員變量
     class InnerClass { //成員內(nèi)部類
     }
}

實(shí)例:

一個(gè)類作為另一個(gè)類的成員(不是作為成員變量,作為成員變量的話就成組合模式了)排截,同時(shí)成員內(nèi)部類可以無(wú)條件的使用外部類的一切靜態(tài)變量嫌蚤、成員變量、靜態(tài)方法断傲、成員方法脱吱,用于內(nèi)部類和外部類通信。

public class OuterClass {
    private String name;

    public OuterClass(String name) {
        this.name = name;
    }

    // 成員內(nèi)部類认罩,類比對(duì)象的成員變量
    private class InnerClass {
        int innerPrice;

        public InnerClass(int innerPrice) {
            System.out.println("成員內(nèi)部類~類比對(duì)象的成員變量");
            this.innerPrice = innerPrice;
        }

        public void print() {
            helloInnerClass();
            System.out.println("出售:" + name + " 單價(jià):" + innerPrice);
        }
    }

    public void helloInnerClass() {
        System.out.println("我是外部類的helloInnerClass方法箱蝠,內(nèi)部類你可以調(diào)用我");
    }

    public static void main(String[] args) {
        OuterClass sample = new OuterClass("香蕉");
        InnerClass inner = sample.new InnerClass(20);
        inner.print();
    }
}

運(yùn)行結(jié)果:

成員內(nèi)部類~類比對(duì)象的成員變量
我是外部類,內(nèi)部類你可以調(diào)用我
出售:香蕉 單價(jià):20

2.2 局部?jī)?nèi)部類

局部?jī)?nèi)部類和局部變量一樣垦垂,都是在方法內(nèi)定義的宦搬,其有效范圍只在方法內(nèi)有效。

一般格式:

public class OuterClass { //外部類
    public void print(){ // print方法
         class InnerClass { //局部?jī)?nèi)部類
         }
    }
}

實(shí)例:

局部?jī)?nèi)部類可以無(wú)條件的使用外部類的一切靜態(tài)變量乔外、成員變量床三、靜態(tài)方法、成員方法杨幼,用于內(nèi)部類和外部類通信撇簿。

public class OuterClass {

    private String name;

    public OuterClass(String name) {
        this.name = name;
    }

    public void helloInnerClass() {
        System.out.println("我是外部類的helloInnerClass方法聂渊,內(nèi)部類你可以調(diào)用我");
    }

    public void print(int price) {
        // 局部?jī)?nèi)部類,類比方法內(nèi)的局部變量
        class InnerClass {
            int innerPrice;

            public InnerClass(int innerPrice) {
                System.out.println("局部?jī)?nèi)部類~類比方法內(nèi)的局部變量");
                this.innerPrice = innerPrice;
            }

            public void sell() {
                helloInnerClass();
                System.out.println("出售:" + name + " 單價(jià):" + innerPrice);
            }
        }
        InnerClass apple = new InnerClass(price);
        apple.sell();
    }

    public static void main(String[] args) {
        OuterClass outerClass = new OuterClass("蘋果");
        outerClass.print(10);
    }
}

運(yùn)行結(jié)果:

局部?jī)?nèi)部類~類比方法內(nèi)的局部變量
我是外部類的helloInnerClass方法四瘫,內(nèi)部類你可以調(diào)用我
出售:蘋果 單價(jià):10

2.3 靜態(tài)內(nèi)部類

靜態(tài)內(nèi)部類和靜態(tài)變量類似汉嗽,它都是使用static關(guān)鍵字修飾。
靜態(tài)內(nèi)部類可以擁有private訪問(wèn)權(quán)限找蜜、protected訪問(wèn)權(quán)限饼暑、public訪問(wèn)權(quán)限及包訪問(wèn)權(quán)限。

一般格式:

public class OuterClass { //外部類
   class InnerClass { //靜態(tài)內(nèi)部類
   }     
}

實(shí)例:

靜態(tài)內(nèi)部類只能使用外部類的一切成員變量洗做、成員方法弓叛,用于內(nèi)部類和外部類通信。

public class OuterClass {
    private static String name="靜態(tài)內(nèi)部類";

    // 靜態(tài)內(nèi)部類诚纸,類比類的靜態(tài)變量
    private static class InnerClass {
        public void print() {
            System.out.println(name+"~類比類的的靜態(tài)變量");
        }
    }

    public static void main(String[] args) {
        OuterClass.InnerClass sample = new OuterClass.InnerClass();
        sample.print();
    }
}

運(yùn)行結(jié)果:

靜態(tài)內(nèi)部類~類比類的的靜態(tài)變量

2.4 匿名內(nèi)部類

匿名內(nèi)部類就是沒(méi)有名字的內(nèi)部類撰筷,其名稱由Java編譯器給出,一般是形如:“外部類名稱+$+匿名類順序”畦徘,沒(méi)有名稱也就是其他地方就不能引用毕籽。其必須要實(shí)現(xiàn)一個(gè)接口或者繼承一個(gè)父類,主要是用來(lái)簡(jiǎn)化代碼井辆,常常用于Swing程序設(shè)計(jì)中的事件監(jiān)聽處理关筒。

一般格式:

public class OuterClass { //外部類
   public void print(){ // print方法
         new InnerClass(){
           ...  
         };
    }     
}

實(shí)例:

匿名內(nèi)部類只能使用外部類的一切成員變量、成員方法杯缺,用于內(nèi)部類和外部類通信蒸播。

定義一個(gè)接口

public interface InnerClass {
    // 接口方法默認(rèn)public
    void print();
}

定義一個(gè)外部類

public class OuterClass {

    public static void print(InnerClass innerClass) {
        innerClass.print();
    }

    public static void main(String[] args) {
        OuterClass.print(new InnerClass() {
            @Override
            public void print() {
                System.out.println("匿名內(nèi)部類~由于沒(méi)有引用,每次新創(chuàng)建的萍肆,在Minor GC時(shí)被清除");
            }
        });
    }
}

運(yùn)行結(jié)果:

匿名內(nèi)部類~由于沒(méi)有引用廉赔,每次新創(chuàng)建的,在Minor GC時(shí)被清除

匿名內(nèi)部類的名稱:外部類名稱+$+匿名類順序

匿名內(nèi)部類的名稱

使用JDK8提供的lambda表示替換匿名內(nèi)部類

public class OuterClass {

    public static void print(InnerClass innerClass) {
        innerClass.print();
    }

    public static void main(String[] args) {
        OuterClass.print(() -> System.out.println("匿名內(nèi)部類~由于沒(méi)有引用匾鸥,每次新創(chuàng)建的蜡塌,在Minor GC時(shí)被清除"));
    }
}

匿名內(nèi)部類在Swing中的實(shí)例:

import javax.swing.*;
import java.awt.*;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class test extends JFrame{
    JPasswordField passwordField;
    JTextField textField;
        test(){
            super();
            setTitle("QQ");
            setBounds(100, 100, 380, 280); 
            getContentPane().setLayout(null); 
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
             
            textField = new JTextField("密碼");
            textField.setBounds(100, 155, 120, 21);
            getContentPane().add(textField);
            // new MouseAdapter()使用匿名內(nèi)部類
            textField.addMouseListener(new MouseAdapter(){
                @Override
                public void mouseClicked(MouseEvent e) {
                    getContentPane().remove(textField);
                    passwordField = new JPasswordField();
                    passwordField.setBounds(100, 155, 120, 21); 
                    getContentPane().add(passwordField);
                }
            });
             
        }
        public static void main(String[] args) {
            new test().setVisible(true);;
        }
}

在給textField添加鼠標(biāo)監(jiān)聽事件的時(shí)候,使用了new MouseAdapter(){}匿名內(nèi)部類作為方法的參數(shù)勿负。

3. 深入理解內(nèi)部類

1. 為什么成員內(nèi)部類可以無(wú)條件訪問(wèn)外部類的成員和類屬性馏艾?
成員內(nèi)部類可以無(wú)條件訪問(wèn)外部類的成員變量、static變量奴愉、成員函數(shù)和static函數(shù)琅摩。

public class Outter {
    private static int b = 2;
    private int a = 1;

    protected class Inner {
        public Inner() {
            System.out.println(a);//成員變量
            System.out.println(b);//static變量
            print();//成員函數(shù)
            staticPrint();//static函數(shù)
        }
    }
    private void print() {
    }

    private static void staticPrint() {
    }
}

我們通過(guò)反編譯字節(jié)碼文件看看究竟是如何實(shí)現(xiàn)的。在編譯時(shí)锭硼,會(huì)將內(nèi)部類單獨(dú)編譯成一個(gè)字節(jié)碼文件房资。

字節(jié)碼文件

Outter.class是外部類的字節(jié)碼文件,Outter$Inner.class才是成員內(nèi)部類的字節(jié)碼文件檀头。

反編譯Outter$Inner.class文件

javap -v Outter$Inner.class

得到一個(gè)關(guān)鍵信息

final cn.lastwhisper.javabasic.InnerClass.member.Outter this$0;

這是一個(gè)指向外部類對(duì)象的指針轰异。也就是說(shuō)編譯器會(huì)默認(rèn)為成員內(nèi)部類添加了一個(gè)指向外部類對(duì)象的引用岖沛,那么這個(gè)引用是如何賦初值的呢?下面接著看內(nèi)部類的構(gòu)造器:

public cn.lastwhisper.javabasic.InnerClass.member.Outter$Inner(cn.lastwhisper.javabasic.InnerClass.member.Outter);

從這里可以看出搭独,雖然我們?cè)诙x的內(nèi)部類的構(gòu)造器是無(wú)參構(gòu)造器婴削,編譯器還是會(huì)默認(rèn)添加一個(gè)參數(shù),該參數(shù)的類型為指向外部類對(duì)象的一個(gè)引用牙肝,所以成員內(nèi)部類中的Outter this&0 指針便指向了外部類對(duì)象唉俗,因此可以在成員內(nèi)部類中隨意訪問(wèn)外部類的成員。從這里也間接說(shuō)明了成員內(nèi)部類是依賴于外部類的配椭,如果沒(méi)有創(chuàng)建外部類的對(duì)象虫溜,則無(wú)法對(duì)Outter this&0引用進(jìn)行初始化賦值,也就無(wú)法創(chuàng)建成員內(nèi)部類的對(duì)象了股缸。

2. 為什么靜態(tài)內(nèi)部類只能訪問(wèn)外部類的成員屬性吼渡?
靜態(tài)內(nèi)部類只能訪問(wèn)外部類的static變量和static函數(shù)。

public class Outter {
    private static int b = 2;
    private int a = 1;

    protected static class Inner {
        public Inner() {
            //System.out.println(a);//成員變量 會(huì)報(bào)錯(cuò)“Non-static field 'a' cannot be referenced from a static context”
            System.out.println(b);//static變量
            //print();//成員函數(shù) 會(huì)報(bào)錯(cuò)“Non-static field 'a' cannot be referenced from a static context”
            staticPrint();//static函數(shù)
        }
    }

    private void print() {
    }

    private static void staticPrint() {
    }
}

如果靜態(tài)內(nèi)部類使用外部類的成員變量乓序,就會(huì)報(bào)錯(cuò)“Non-static field 'a' cannot be referenced from a static context”,從字面意思很好理解坎背,非static字段不能被static上下文所引用替劈。靜態(tài)內(nèi)部類使用外部類的成員函數(shù)情況也類似。

類比著上一個(gè)問(wèn)題得滤,通過(guò)反編譯字節(jié)碼文件陨献,發(fā)現(xiàn)編譯器在編譯時(shí)并沒(méi)有添加外部類的引用,所以靜態(tài)內(nèi)部類也無(wú)法使用外部類的成員變量和成員函數(shù)懂更。

public cn.lastwhisper.javabasic.InnerClass.Static.Outter$Inner();

3. 為什么匿名內(nèi)部類只能訪問(wèn)final修飾的局部變量眨业?

在JDK8以前匿名內(nèi)部類只能訪問(wèn)final修飾的局部變量,在JDK8以后匿名內(nèi)部類可以訪問(wèn)非final修飾的局部變量

想必這個(gè)問(wèn)題也曾經(jīng)困擾過(guò)很多人沮协,在討論這個(gè)問(wèn)題之前龄捡,先看下面這段代碼:

public class FinalTest {
    public void test(final int b) {
        final int a = 100;
        new Thread() {
            public void run() {
                System.out.println(a);
                System.out.println(b);
            }
        }.start();
    }
}

這段代碼會(huì)被編譯成兩個(gè)class文件:FinalTest$1.class和FinalTest.class

匿名內(nèi)部類字節(jié)碼文件

默認(rèn)情況下,編譯器會(huì)為匿名內(nèi)部類起名為“外部類名稱+$+匿名類順序”

即test方法里面的匿名內(nèi)部類為:FinalTest$1.class

上段代碼中慷暂,如果把變量a和b前面的任一個(gè)final去掉聘殖,這段代碼都編譯不過(guò)。我們先考慮這樣一個(gè)問(wèn)題:

當(dāng)test方法執(zhí)行完畢之后行瑞,局部變量a的生命周期就結(jié)束了奸腺,而此時(shí)Thread對(duì)象的生命周期很可能還沒(méi)有結(jié)束,那么在Thread的run方法中繼續(xù)訪問(wèn)test方法的局部變量a就變成不可能了血久,但是又要實(shí)現(xiàn)這樣的效果突照,怎么辦呢?Java采用了 復(fù)制 的手段來(lái)解決這個(gè)問(wèn)題氧吐。將這段代碼的字節(jié)碼反編譯可以得到下面的內(nèi)容:

反編譯FinalTest$1.class

得到的信息很多讹蘑,我們分成兩個(gè)部分末盔。
第一部分run方法

run方法

我們看到在run方法中有一條指令:

bipush 100

這條指令表示將操作數(shù)100壓棧,表示使用的是一個(gè)本地局部變量衔肢。這個(gè)過(guò)程是在編譯期間由編譯器默認(rèn)進(jìn)行庄岖,如果這個(gè)變量的值在編譯期間可以確定,則編譯器默認(rèn)會(huì)在匿名內(nèi)部類的常量池中添加一個(gè)內(nèi)容相等的字面量或者直接將相應(yīng)的字節(jié)碼嵌入到執(zhí)行字節(jié)碼中角骤。

這樣一來(lái)隅忿,匿名內(nèi)部類方法中引用的變量其實(shí)并不是外部類方法中的局部變量,而是引用編譯器在匿名內(nèi)部類的常量池中添加的一個(gè)內(nèi)容相等的字面量邦尊。即匿名內(nèi)部類run方法中使用的a并不是test方法中的a背桐,而是FinalTest$1常量池中的a=100。

第二部分匿名內(nèi)部類的構(gòu)造函數(shù)

匿名內(nèi)部類的構(gòu)造函數(shù)

我們看到匿名內(nèi)部類FinalTest$1的構(gòu)造器含有兩個(gè)參數(shù)蝉揍,一個(gè)是指向外部類對(duì)象的引用链峭,一個(gè)是int型變量,很顯然又沾,這里是將變量test方法中的形參b以參數(shù)的形式傳進(jìn)來(lái)對(duì)匿名內(nèi)部類中的拷貝(變量b的復(fù)制)進(jìn)行賦值初始化弊仪。

也就說(shuō)如果局部變量的值在編譯期間就可以確定,則直接在匿名內(nèi)部里面創(chuàng)建一個(gè)拷貝杖刷。如果局部變量的值無(wú)法在編譯期間確定励饵,則通過(guò)構(gòu)造器傳參的方式來(lái)對(duì)拷貝進(jìn)行初始化賦值。

這樣一來(lái)就解決了前面所說(shuō)的生命周期不一致的問(wèn)題滑燃。但是新的問(wèn)題又來(lái)了役听,既然在run方法中訪問(wèn)的變量a和test方法中的變量a不是同一個(gè)變量,當(dāng)在run方法中改變變量a的值的話表窘,會(huì)出現(xiàn)什么情況典予?

對(duì),會(huì)造成數(shù)據(jù)不一致性乐严,這樣就達(dá)不到原本的意圖和要求瘤袖。為了解決這個(gè)問(wèn)題,java編譯器就限定必須將變量a限制為final變量昂验,不允許對(duì)變量a進(jìn)行更改(對(duì)于引用類型的變量孽椰,是不允許指向新的對(duì)象),這樣數(shù)據(jù)不一致性的問(wèn)題就得以解決了凛篙。

至此我們可以回答“為什么匿名內(nèi)部類只能訪問(wèn)final修飾的局部變量黍匾?”了。

1. Java為了避免數(shù)據(jù)不一致性的問(wèn)題呛梆,做出了匿名內(nèi)部類只可以訪問(wèn)final的局部變量的限制锐涯。

2. 補(bǔ)充:Java為了局部變量與匿名內(nèi)部類生命周期不一致的問(wèn)題,將匿名內(nèi)部類使用到的外部類方法局部變量復(fù)制到自己的常量池中一份填物,操作時(shí)只使用自己常量池中的數(shù)據(jù)纹腌。

4. 為什么需要內(nèi)部類

至此我們已經(jīng)看到了許多描述內(nèi)部類的語(yǔ)法和語(yǔ)義霎终,但是這并不能回答“為什么需要內(nèi)部類” 這個(gè)問(wèn)題。

一般說(shuō)來(lái)升薯,內(nèi)部類繼承自某個(gè)類或?qū)崿F(xiàn)某個(gè)接口莱褒,內(nèi)部類的代碼操作創(chuàng)建它的外圍類的對(duì)象。所以可以認(rèn)為內(nèi)部類提供了某種進(jìn)入其外圍類的窗口涎劈。

內(nèi)部類必須要回答的一個(gè)問(wèn)題是:如果只是需要一個(gè)對(duì)接口的引用广凸,為什么不通過(guò)外圍類實(shí)現(xiàn)那個(gè)接口呢?答案是:“如果這能滿足需求蛛枚,那么就應(yīng)該這樣做谅海。” 那么內(nèi)部類實(shí)現(xiàn)一個(gè)接口與外圍類實(shí)現(xiàn)這個(gè)接口有什么區(qū)別呢蹦浦?答案是:后者不是總能享用到接口帶來(lái)的方便扭吁, 有時(shí)需要用到接口的實(shí)現(xiàn)。所以盲镶,使用內(nèi)部類最吸引人的原因是 :

每個(gè)內(nèi)部類都能獨(dú)立地繼承自一個(gè)(接口的)實(shí)現(xiàn)侥袜,所以無(wú)論外圍類是否已經(jīng)繼承了某個(gè)(接口的)實(shí)現(xiàn),對(duì)于內(nèi)部類都沒(méi)有影響溉贿。

內(nèi)部類使得多重繼承的解決方案變得完整枫吧。接口解決了部分問(wèn)題,而內(nèi)部類有效地實(shí)現(xiàn)了 “多重繼承” 顽照。 也就是說(shuō),內(nèi)部類允許繼承多個(gè)非接口類型(類或抽象類)闽寡。

實(shí)例:

使用一個(gè)類繼承兩個(gè)抽象類代兵,模擬“多繼承問(wèn)題”

abstract class MyClass1 { }
abstract class MyClass2 { }

/**
 * 成員內(nèi)部類實(shí)例
 * @author lastwhisper
 */
public class OuterClass extends MyClass1 {
    private String name;

    public OuterClass(String name) {
        this.name = name;
    }

    // 成員內(nèi)部類,類比對(duì)象的成員變量
    class InnerClass extends MyClass2 {
        int innerPrice;

        public InnerClass(int innerPrice) {
            System.out.println("成員內(nèi)部類~類比對(duì)象的成員變量");
            this.innerPrice = innerPrice;
        }

        public void print() {
            helloInnerClass();
            System.out.println("出售:" + name + " 單價(jià):" + innerPrice);
        }
    }

    public void helloInnerClass() {
        System.out.println("我是外部類的helloInnerClass方法爷狈,內(nèi)部類你可以調(diào)用我");
    }

    public static void main(String[] args) {
        OuterClass sample = new OuterClass("香蕉");
        InnerClass inner = sample.new InnerClass(20);
        inner.print();
    }
}

如果不需要解決“多重繼承” 的問(wèn)題植影,那么自然可以用別的方式編碼,而不需要使用內(nèi)部類涎永。但如果使用內(nèi)部類思币,還可以獲得其他一些特性:

  1. 內(nèi)部類可以有多個(gè)實(shí)例,每個(gè)實(shí)例都有自己的狀態(tài)信息羡微,并且與其外圍類對(duì)象的信息相互獨(dú)立谷饿。
  2. 在單個(gè)外圍類中,可以讓多個(gè)內(nèi)部類以不同的方式實(shí)現(xiàn)同一個(gè)接口妈倔,或繼承同一個(gè)類博投。
  3. 創(chuàng)建內(nèi)部類對(duì)象的時(shí)刻并不依賴于外圍類對(duì)象的創(chuàng)建。
  4. 內(nèi)部類并沒(méi)有令人迷惑的“is-a”關(guān)系盯蝴; 它就是一個(gè)獨(dú)立的實(shí)體 毅哗。

5. 總結(jié)

訪問(wèn)權(quán)限:

  1. 成員內(nèi)部類和靜態(tài)內(nèi)部類可以擁有private訪問(wèn)權(quán)限听怕、protected訪問(wèn)權(quán)限、public訪問(wèn)權(quán)限及包訪問(wèn)權(quán)限虑绵。
  2. 如果成員內(nèi)部類Inner用private修飾尿瞭,則只能在外部類的內(nèi)部訪問(wèn),如果用public修飾翅睛,則任何地方都能訪問(wèn)声搁;如果用protected修飾,則只能在同一個(gè)包下或者繼承外部類的情況下訪問(wèn)宏所;如果是默認(rèn)訪問(wèn)權(quán)限酥艳,則只能在同一個(gè)包下訪問(wèn)。
  3. 這一點(diǎn)和外部類有一點(diǎn)不一樣爬骤,外部類只能被public和包訪問(wèn)兩種權(quán)限修飾充石。我個(gè)人是這么理解的,由于成員內(nèi)部類看起來(lái)像是外部類的一個(gè)成員霞玄,所以可以像類的成員一樣擁有多種權(quán)限修飾骤铃。

資源使用:

  1. 成員內(nèi)部類可以無(wú)條件的使用外部類的一切靜態(tài)變量、成員變量坷剧、靜態(tài)方法惰爬、成員方法,用于內(nèi)部類和外部類通信惫企。
  2. 局部?jī)?nèi)部類可以無(wú)條件的使用外部類的一切靜態(tài)變量撕瞧、成員變量、靜態(tài)方法狞尔、成員方法丛版,用于內(nèi)部類和外部類通信。
  3. 靜態(tài)內(nèi)部類只能使用外部類的一切成員變量偏序、成員方法页畦,用于內(nèi)部類和外部類通信。
  4. 匿名內(nèi)部類只能使用外部類的一切成員變量研儒、成員方法豫缨,用于內(nèi)部類和外部類通信。

使用內(nèi)部類的好處:

  1. 可以解決“多繼承問(wèn)題”
  2. 內(nèi)部類可以有多個(gè)實(shí)例端朵,每個(gè)實(shí)例都有自己的狀態(tài)信息好芭,并且與其外圍類對(duì)象的信息相互獨(dú)立。
  3. 在單個(gè)外圍類中冲呢,可以讓多個(gè)內(nèi)部類以不同的方式實(shí)現(xiàn)同一個(gè)接口栓撞,或繼承同一個(gè)類。
  4. 創(chuàng)建內(nèi)部類對(duì)象的時(shí)刻并不依賴于外圍類對(duì)象的創(chuàng)建。
  5. 內(nèi)部類并沒(méi)有令人迷惑的“is-a”關(guān)系瓤湘; 它就是一個(gè)獨(dú)立的實(shí)體 瓢颅。

參考

《Java編程思想》
https://www.cnblogs.com/dolphin0520/p/3811445.html
https://www.cnblogs.com/cuipengfei/p/3150542.html#3901831

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市弛说,隨后出現(xiàn)的幾起案子挽懦,更是在濱河造成了極大的恐慌,老刑警劉巖木人,帶你破解...
    沈念sama閱讀 216,402評(píng)論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件信柿,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡醒第,警方通過(guò)查閱死者的電腦和手機(jī)渔嚷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)稠曼,“玉大人形病,你說(shuō)我怎么就攤上這事∠挤” “怎么了漠吻?”我有些...
    開封第一講書人閱讀 162,483評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)司恳。 經(jīng)常有香客問(wèn)我途乃,道長(zhǎng),這世上最難降的妖魔是什么扔傅? 我笑而不...
    開封第一講書人閱讀 58,165評(píng)論 1 292
  • 正文 為了忘掉前任耍共,我火速辦了婚禮,結(jié)果婚禮上猎塞,老公的妹妹穿的比我還像新娘试读。我一直安慰自己,他們只是感情好邢享,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評(píng)論 6 388
  • 文/花漫 我一把揭開白布鹏往。 她就那樣靜靜地躺著淡诗,像睡著了一般骇塘。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上韩容,一...
    開封第一講書人閱讀 51,146評(píng)論 1 297
  • 那天款违,我揣著相機(jī)與錄音,去河邊找鬼群凶。 笑死插爹,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播赠尾,決...
    沈念sama閱讀 40,032評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼力穗,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了气嫁?” 一聲冷哼從身側(cè)響起当窗,我...
    開封第一講書人閱讀 38,896評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎寸宵,沒(méi)想到半個(gè)月后崖面,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,311評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡梯影,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評(píng)論 2 332
  • 正文 我和宋清朗相戀三年巫员,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片甲棍。...
    茶點(diǎn)故事閱讀 39,696評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡简识,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出救军,到底是詐尸還是另有隱情财异,我是刑警寧澤,帶...
    沈念sama閱讀 35,413評(píng)論 5 343
  • 正文 年R本政府宣布唱遭,位于F島的核電站戳寸,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏拷泽。R本人自食惡果不足惜疫鹊,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望司致。 院中可真熱鬧拆吆,春花似錦、人聲如沸脂矫。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)庭再。三九已至捞奕,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間拄轻,已是汗流浹背颅围。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留恨搓,地道東北人院促。 一個(gè)月前我還...
    沈念sama閱讀 47,698評(píng)論 2 368
  • 正文 我出身青樓筏养,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親常拓。 傳聞我的和親對(duì)象是個(gè)殘疾皇子渐溶,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容

  • 一、內(nèi)部類介紹 內(nèi)部類:將一個(gè)類的定義放在另一個(gè)類的定義內(nèi)部弄抬。 內(nèi)部類是個(gè)編譯時(shí)的概念掌猛,一旦編譯成功后,它就與外圍...
    代碼米蟲閱讀 501評(píng)論 0 0
  • 1眉睹、內(nèi)部類分類: 成員內(nèi)部類 局部?jī)?nèi)部類 匿名內(nèi)部類 靜態(tài)內(nèi)部類 2荔茬、成員內(nèi)部類 1.概念: 定義在一個(gè)類內(nèi)部的類...
    M_JCs閱讀 902評(píng)論 0 9
  • 什么是內(nèi)部類?為什么要使用內(nèi)部類竹海? ?內(nèi)部類是指在類的內(nèi)部可以定義另一個(gè)類慕蔚。內(nèi)部類可以申明成public或priv...
    小任務(wù)大夢(mèng)想閱讀 298評(píng)論 0 0
  • 內(nèi)部類:類里面再聲明類 1》默認(rèn)內(nèi)部類 class Outer{ private int a = 12; clas...
    沈默的頭號(hào)狗腿閱讀 98評(píng)論 0 0
  • 今年的4月5日,清明節(jié)斋配,我和L走到了一起孔飒。 她算我的第二個(gè)女朋友。 今天我和她分開艰争,整整六個(gè)月的時(shí)間坏瞄。 決絕之后,...
    名再道號(hào)直行閱讀 441評(píng)論 0 1