Java Nested Class嵌套類詳解

這是一篇對Java Nested Class基礎知識的復習,也是掌握Java 8 Lambda原理的基礎。能力有限,希望能把嵌套類的相關內容說清楚。

嵌套類 Nested Class就是在一個class定義的內部定義另外一個類。

分類

Java中一般規(guī)定類的定義文件中只能定義一個Public Class,并且公有類名需要和類的物理文件名保持一致,不然編譯器會報錯。這個是Java的基本原則。

有些代碼組織會希望將這個公有類密切相關的類,與共有類放在一起。那么這個時候可以選擇:

  1. 在同一個文件中,定義包私有類,或私有類。也就是說在Public文件外定義類。
  2. 在公有類內部,再定義一個類。

第二種方式定義的類就是本文的主題,嵌套類(Nested Class)!

嵌套類能夠在任意的代碼塊Block中嵌套,通常情況下嵌套的范圍主要是2類:

  1. 在Public Class范圍內嵌套,換句話說就是一個類的定義作為類的Member。
  2. 在靜態(tài)塊、方法、條件判斷或者循環(huán)代碼塊中嵌套,換句話說就是代碼塊中的一個Variable。

對于第一種嵌套類,可以增加訪問限定符 public, protected, private 來修飾允許訪問范圍,也可以增加static關鍵詞;而第二種嵌套類則不能加任何的限定符。

對于加了static的嵌套類,則稱為靜態(tài)嵌套類;對于沒加static的嵌套類,則稱為非靜態(tài)嵌套類,又經常被稱為內部類(inner class)。

總結靜態(tài)嵌套類和內部類的區(qū)別,如下表:

靜態(tài)嵌套類 內部類
生命周期 獨立于被嵌套類 依賴被嵌套類,只有在被嵌套類實例化后才可使用
訪問權限 不能訪問被嵌套類的成員 能夠訪問被嵌套類的任何成員,包含private
能否擁有靜態(tài)成員 可以 不能

下面就每一個區(qū)別分別舉幾個例子說明:

生命周期

靜態(tài)嵌套類

public class Car {

    private String vendorName;
    private Tier[] tiers;

    public Car(String vendorName, Tier tier) {
        this.vendorName = vendorName;
        Tier[] tiers = new Tier[4];
        for (int i = 0; i < 4; i++) {
            tiers[i] = tier.clone();
        }
    }

    private static class Tier {
        private int size;

        public int getSize() {
            return size;
        }

        public void setSize(int size) {
            this.size = size;
        }

        public Tier(int size) {
            this.size = size;
        }

        protected Tier clone() {
            return new Tier(this.getSize());
        }
    }

    @Override
    public String toString() {
        return "Car{" +
                "vendorName='" + vendorName + '\'' +
                ", tiers=" + Arrays.toString(tiers) +
                '}';
    }

    public static void main(String[] args) {
        Car car = new Car("Toyota", new Tier(17));
    }
}

非靜態(tài)嵌套類

內部類

局部本地類 (local classes)

匿名類(anonymous classes)

Java 中匿名類——Lambda

inner class能訪問嵌套類的屬性,包括private
static nested class不能訪問嵌套類的成員

static nested class 的實例可以脫離外部類的生命周期獨立存在,通過 OutterClass.StaticInnerClass instantce = new OutterClass.StaticInnerClass();來創(chuàng)建實例

inner class的實例無法脫離外部類的生命周期獨立存在,要實例化一個inner class,必須先實例化相應的outer class,使用以下語法實例化inner class:
OuterClass.InnerClass innerObject = outerObject.new InnerClass();

inner class不能生命任何的靜態(tài)成員

inner class 的兩種特殊類型 local classes anonymous classes

local class是定義在代碼塊內部的,經常會出現(xiàn)在方法體內部。local class可以訪問類的成員。local class也可以訪問塊的本地變量,不過要求本地變量一定要是final的。因為會捕獲(capture)相應的值(captrued variable)在Java8開始,本地變量可以訪問effectively final的變量,翻譯為等價final可能比較合適,就是初始化時候從來不改變的值,編譯器會等同于final。java 8 開始,方法的本地類也可以訪問方法的參數(shù)。shadowing規(guī)則同inner class的shadow規(guī)則

不能在塊內定義接口,因為接口天然是靜態(tài)的。實例方法不是一個靜態(tài)的上下文。local cass內部不能定義static方法,只能定義static的常量

匿名類anonymous class與local class類似,只是沒有名稱。如果類只使用一次,可以使用匿名類。如果說Local class是類聲明,那么匿名類就是表達式

訪問規(guī)則:
匿名類可以訪問外部類的成員
匿名類不能訪問非final或effectively final的本地變量
匿名類內部的變量生命將屏蔽所有外部的同名變量。通過this, ClassName.this進行訪問

同local class,匿名類的成員也有限制:
不能聲明靜態(tài)的方法或接口
能夠擁有常量的靜態(tài)成員

匿名類內可以生命:字段、另外的方法、實例初始化器?,本地類。但不能聲明構造器(因為沒有名字)

如果匿名類只有一個方法,那么在Java 8中可以使用 Lambda表達式替代

java.util.function

inner class 同名變量的查找策略
method parameter, this.variableName(inner class), OuterClassName.this.variableName.

inner classes的序列化將遇到很大挑戰(zhàn)。不同的編譯器實現(xiàn)將影響代碼的可移植性,因為inner class的構造器是編譯器生成的。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,734評論 18 399
  • Java 內部類 分四種:成員內部類、局部內部類、靜態(tài)內部類和匿名內部類。 1、成員內部類: 即作為外部類的一個成...
    ikaroskun閱讀 1,358評論 0 13
  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,614評論 19 139
  • Android圖片是必不可少的,在一些大的應用都會有選擇圖片或者發(fā)送剛剛拍攝的圖片的功能,現(xiàn)在我們就來實現(xiàn)一個調用...
    楓羽望空閱讀 1,497評論 0 2
  • 新加坡游玩第一天,早起的我很是焦慮。攻略沒做,地圖沒拿,我的新加坡之行除了安排好了機票酒店、外加預訂了幾張門票,其...
    學前班77閱讀 265評論 6 4

友情鏈接更多精彩內容