Java各類稱呼類詳解

 Java有各類各樣類,內部類、嵌套類、成員類、局部類(本地類)、靜態類、匿名類、文件類以及這些組合起來的稱呼類,成員內部類,成員匿名類,成員嵌套類,本地匿名類等,真是多的不行,但有些實際上是一個意思,在這裏好好理一理。java

聲明

  1.注意,這些稱呼都是翻譯過來的,可是同一個英文單詞或一個詞組翻譯過來可能有不一樣叫法,好比local nested class,local有局部、本地意思,實際上是一個意思,local nested class翻譯過來就是局部嵌套類(本地嵌套類),又由於非靜態嵌套類都稱爲內部類,因此local nested class又叫爲內部局部類(本地內部類),最終又簡稱爲:局部類(本地類)。我我的以爲局部類更加形象點因此下面都優先採用局部類一說。 
  2.我經過搜索找到兩種不太相同的內部類定義,一種認爲:定義在類裏面的稱爲嵌套類(nested class),而非靜態嵌套類纔是內部類(inner class),也就是說嵌套類包含內部類;另一種則是認爲:定義在類裏面的稱爲內部類,這樣靜態嵌套類也是內部類,也就是說嵌套類=內部類。可是,第一種纔是Java語言規範規定的,我一開始不肯定,找到Java7的語言規範驗證,結果確實如此,即第一種纔是正確的,那麼問題來了:依照第一種劃分,靜態內部類實際上是一種錯誤說法。。。只有靜態嵌套類,內部類是沒有靜態一說的! 
  可是對於大多數中國程序員,貌似將定義在類裏面的類稱爲內部類不是更符合文意麼?也許這就是爲何會有這麼多人一直認爲靜態內部類的存在。嘛,反正無論怎麼稱呼,只要知道表明什麼意思就好,細節什麼的不要在乎(光哥:因此不注意細節的你寫的代碼才這麼一大堆bug麼?還不趕忙去改(怒吼))。 
  我這裏採用Java語言規範上說的。程序員

0.文件類

  文件類放在最前面,是由於文件類是與主類(一個文件中public類)關係最不密切的一類。什麼是文件類?看代碼就知道:express

public class Main{}
class Test{}//Test就是文件類
//是的,一個.java文件裏面定義在主類外面的就是文件類
//主類、文件類稱爲頂級類(top level class),Java語言規範中定義:非嵌套類即爲頂級類。

【注意】:主類這必定義是我本身按語義稱呼的,有的地方稱爲基本類,但我以爲很不符合語義,Java語言規範我也沒找到相關定義。ide

  1. 由於一個.java文件只能有一個主類(public 類),因此文件類默認只能是包訪問權限,即:不是同一個包的是沒法引入和使用的。

1.嵌套類

  由上面文件類可有相似定義:一個.java文件裏面定義在類裏面的就是嵌套類,定義在類內部,包括塊、靜態塊、構造器、方法內。這個時候該類也相對來被稱爲包裝類(enclosing class)或外部類。 
  嵌套類是能夠有層次的,也就是說嵌套類裏面還能夠定義類,成爲嵌套類中的嵌套類。 
  在Java語言規範裏面,嵌套類定義是:spa

A nested class is any class whose declaration occurs within the body of 
another class or interface.

  說的簡單一點,就是定義在類(這裏還包括接口,下同)裏面的類。因此說,如下全部的類均可以稱爲嵌套類。嵌套類分爲兩種:靜態嵌套類和非靜態嵌套類,非靜態嵌套類就是內部類(inner class)。.net

靜態嵌套類

  簡稱靜態類,和主類關係也不大,只是在其餘類中引用使用的時候須要加上外部類限定,但在技術上來看,徹底是兩個獨立無關係的類。翻譯

public class Main{
    public static class NestClass{}
}
//在外面使用時候形式以下,在Main中使用則不須要加上外部類限定
Main.NestClass nestClass = new Main.NestClass();

  從形式上來看,靜態類能夠說是類的一個靜態成員(因此也能夠說是成員類一種),但從技術上來看,其實兩者沒什麼關係,能夠看作第三類頂級類。但也所以,靜態類不怎麼經常使用,由於它同通常類沒什麼優點可言。code

  1. 靜態類不能訪問外部類的非靜態成員和非靜態方法(不論是public仍是private的);
  2. 靜態類的實例不須要先實例化外部類成員,可直接實例化。

2.內部類

  Java語言規範裏的定義:對象

An inner class is a nested class that is not explicitly or implicitly 
declared static.
//即非靜態嵌套類即爲內部類

內部類包括:成員類、局部類、匿名類。blog

  1. 內部類中不能有靜態修飾的成員(好比塊、字段、方法、接口等),總之不能有static關鍵字,除了一種狀況,那就是靜態常量,又由於常量成員字段必須在聲明的時候初始化,因此形式只能如:public static final int a = 6;
  2. 內部類能夠訪問外部類任何成員,不論是公有的仍是私有的,靜態的仍是非靜態的(而且內部類的成員的名字也能夠同外部相同,只不過這樣會覆蓋掉去外部類的),這是由於每個內部類都保存了一個對外部類的一個引用。這很好理解,由於你要實例化這個內部類,確定是經過外部類的一個實例,而內部類保留的這個引用就是這個外部類實例。
  3. 內部類命名格式:外部類名稱+$+[該種類同名類中該類順序]+[內部類名稱],例如成員類,成員類不能同名,因此也就沒有同名類順序:com.fcc.test.OuterClass$MemberClass;局部類:com.fcc.test.OuterClass$1LocalClass;匿名類:匿名類沒有名稱,因此格式如:com.fcc.OuterClass$1。

成員類

  這裏說的是非靜態成員內部類(若是靜態嵌套類也算是成員類一種的話),non-static member (inner) class。而通常說的也是這種,但從技術上來看,成員類應該還包括靜態嵌套類。

A member class is a class whose declaration is directly enclosed in 
another class or interface declaration.

  成員類算是最多見最經常使用的一種內部類,咱們通常說的內部類說的就是成員類:在類裏面,但不在塊、構造器、方法裏面。

//成員類,從技術上來講,能夠分爲兩種:成員內部類和成員嵌套類。
//1.成員內部類即這裏說的成員類,全稱是非靜態成員內部類
//2.成員嵌套類即上面的靜態嵌套類
public class Main{
    public class MemberClass{}//成員內部類,常簡稱爲成員類
}

  成員類,可使用public,private,protected訪問控制符,也能夠用static,final關鍵字修飾,而且有enclose class屬性。 
這裏題外說明一下:

  1. 成員(member),只要是在類裏面的(但不在塊、構造器、方法內),都是成員:能夠是變量,就是成員變量(通常又稱爲成員字段,Field);能夠是方法,好吧,方法都是成員(由於Java中方法不可能位於類外)的;固然,一樣的,也能夠是接口、枚舉、註釋類以及類。
  2. 關於static理解,有static修飾的是類自己屬性(共性),因此訪問能夠不經過類的實例對象,而非static修飾的,是對象屬性(個性),必須經過類的實例對象訪問,由於個性是個體的屬性啊,固然要建立出個體,而後這個個性纔有意義。
  3. 關於enclose class,enclose method,enclose constructor屬性,能夠理解爲這個類是被類、仍是方法、構造器包裝起來的。關於這些屬性,能夠參考Class類:Java源碼解析(2) —— Class(1)

局部類(本地類)

  local nested class,局部嵌套類,簡稱局部類,局部類所屬範圍:在塊、構造器以及方法內,這裏的塊包括普通塊和靜態塊。局部類只在本塊範圍內有效。 
定義:

A local class is a nested class (§8) that is not a member of any class 
and that has a name.

翻譯過來就是:局部類是嵌套類,但不是成員類,並且有名稱(不是匿名類)。

public class Test {
    {
        class AA{}//塊內局部類
    }
    public Test(){
        class AA{}//構造器內局部類
    }
    public static void main(String[] args){
    }
    public void test(){
        class AA{}//方法內局部類
    }
}
//注意到了吧,能夠同名,編譯後,造成諸如:外部類名稱+$+同名順序+局部類名稱
//Test$1AA.class/Test$2AA.class/Test$3AA.class

  局部類最多隻能有final修飾,但不一樣的是,塊內局部類有enclose class屬性,而構造器局部類有enclose constructor屬性,方法局部類有enclose method屬性,嘛,其實很好理解的吧,一看就知道。

  1. 局部類只能訪問(使用)這個塊中(局部類外)final屬性。這裏的塊包括了上面說的塊、構造器、方法。

匿名類

定義:

An anonymous class declaration is automatically derived from a class 
instance creation expression by the Java compiler

  匿名類,就是沒有名稱的類,其名稱由Java編譯器給出,通常是形如:外部類名稱+$+匿名類順序,沒有名稱也就是其餘地方就不能引用,不能實例化,只用一次,固然也就不能有構造器。 
  匿名類根據位於地方不一樣分爲:成員匿名類和局部匿名類。

public class Test {
    InterfaceA a = new InterfaceA() {};//成員匿名類
    public static void main(String[] args){
        InterfaceA a = new InterfaceA() {};//局部匿名類
        //以上兩種是經過實現接口實現匿名類,稱爲接口式匿名類,也能夠經過繼承類
        Test test = new Test(){};//繼承式匿名類
        //還能夠是位於參數上
        new Thread(new Runnable() {
            @Override
            public void run() {
            }
        }).start();//屬於局部匿名類一種
    }
    private interface InterfaceA{}
}

  匿名類不能使用任何關鍵字和訪問控制符,匿名類和局部類訪問規則同樣,只不過內部類顯式的定義了一個類,而後經過new的方式建立這個局部類實例,而匿名類直接new一個類實例,沒有定義這個類。匿名類最多見的方式就是回調模式的使用,經過默認實現一個接口建立一個匿名類而後,而後new這個匿名類的實例。

總結

  本文討論的是:嵌套類、內部類、成員類、局部類、匿名類相關,這些類的劃分主要是根據類聲明(或位於)的地方劃分的:  1.嵌套類,位於類內部,又分爲:靜態嵌套類和非靜態嵌套類。  2.靜態嵌套類即爲靜態類。靜態類只有這一種,技術來講,也能夠當作靜態成員類。  3.非靜態嵌套類即爲內部類,又分爲:成員類、局部類(本地類)、匿名類。  4.成員類:位於類內部但不包括位於塊、構造器、方法內,且有名稱的類。  5.局部類:位於塊、構造器、方法內的有名稱類。  6.匿名類:類內無名稱類,又可細分爲:成員匿名類和局部匿名類。

相關文章
相關標籤/搜索