Java內部類


  Java內部類或嵌套類是在類或接口中聲明的類。我們使用內部類在一個地方邏輯地分組類和接口,以便它更可讀和可維護。此外,它還可以訪問外部類的成員,包括私有數據成員和方法。

內部類的優點:

  1. 嵌套類代表了一種特殊的類型關系:能訪問外部類的所有數據成員和方法(包括私有的)
  2. 嵌套類用於開發更可讀和可維護的代碼,因為它只在一個地方對類和接口進行邏輯分組。
  3. 代碼優化:它需要更少的代碼

問題:

  1. 編輯器為member inner class(成員內部類)生成的內部代碼是什么?
  2. 創建annonymous inner class(匿名內部類)的兩種方式是什么?
  3. 我們可以在local inner class(局部內部類)中訪問非final局部變量嗎?
  4. 如何訪問static nested class(靜態嵌套類)?
  5. 接口中可以定義類嗎?
  6. 類中可以定義接口嗎?

nested class(嵌套類)和inner class(內部類)的區別於聯系

  內部類是嵌套類的一部分,非靜態嵌套類被視為內部類

嵌套類的類型

  有靜態嵌套類和非靜態嵌套類兩種類型。非靜態嵌套類被視為內部類

  • Non-static nested class (inner class) 非靜態嵌套類:
    1. member inner class(成員內部類)
    2. annonymous inner class(匿名內部類)
    3. local inner class(局部內部類)
  • static nested class靜態嵌套類

1.成員內部類

  在類內部創建但在方法之外的非靜態類稱為成員內部類。語法:

 1 class TestMemberOuter1{  
 2  private int data=30;  
 3  class Inner{  
 4   void msg(){System.out.println("data is "+data);}  
 5  }  
 6  public static void main(String args[]){  
 7   TestMemberOuter1 obj=new TestMemberOuter1();  
 8   TestMemberOuter1.Inner in=obj.new Inner();  
 9   in.msg();  
10  }  
11 }

  成員內部類的工作原理:

  Java編譯器在內部類的情況下創建兩個類文件。內部類的類文件名是“outer$inner”。如果要實例化內部類,則必須創建外部類的實例在這種情況下,內部類的實例是在外部類的實例中創建的。

  編譯器生成的內部代碼:

  java編譯器創建一個名為"outer$inner"的類文件。成員內部類具有外部類的引用,這就是為什么成員內部類可以訪問外部類的所有數據成員的原因

import java.io.PrintStream;  
class Outer$Inner  
{  
    final Outer this$0;  
    Outer$Inner()  
    {   super();  
        this$0 = Outer.this;  
    }  
    void msg()  
    {  
        System.out.println((new StringBuilder()).append("data is ")  
                    .append(Outer.access$000(Outer.this)).toString());  
    }  
}

2.匿名內部類

  一個沒有名字的類在Java中被稱為匿名內部類。如果您必須重寫類或接口的方法,則應該使用它。可以通過兩種方式創建Java匿名內部類 

  1. 類(可以是抽象類或具體類)
  2. 接口

  java匿名內部類舉例

 1 abstract class Person{  
 2   abstract void eat();  
 3 }  
 4 class TestAnonymousInner{  
 5  public static void main(String args[]){  
 6   Person p=new Person(){  
 7   void eat(){System.out.println("nice fruits");}  
 8   };  
 9   p.eat();  
10  }  
11 }  

  匿名內部類的工作原理

  1. 類被創建,但是它的名稱由編譯器決定,編譯器實現Person類,並實現eat方法
  2. 創建匿名類的對象,該對象由Person類型的p引用變量引用。

  編譯器生成的代碼

import java.io.PrintStream;  
static class TestAnonymousInner$1 extends Person  
{  
   TestAnonymousInner$1(){}  
   void eat()  
    {  
        System.out.println("nice fruits");  
    }  
} 

3. 局部內部類

  在方法中創建的類稱為Java中的本地內部類。如果要調用本地內部類的方法,必須在該方法中實例化該類。 

  局部內部類舉例

 1 public class localInner1{  
 2  private int data=30;//instance variable  
 3  void display(){  
 4   class Local{  
 5    void msg(){System.out.println(data);}  
 6   }  
 7   Local l=new Local();  
 8   l.msg();  
 9  }  
10  public static void main(String args[]){  
11   localInner1 obj=new localInner1();  
12   obj.display();  
13  }  
14 }

  編譯器生成的內部類:

 1 import java.io.PrintStream;  
 2 class localInner1$Local  
 3 {  
 4     final localInner1 this$0;  
 5     localInner1$Local()  
 6     {     
 7         super();  
 8         this$0 = Simple.this;  
 9     }  
10     void msg()  
11     {  
12         System.out.println(localInner1.access$000(localInner1.this));  
13     }  
14 } 

  規則:

  1. 局部內部類不能聲明為public、protected、private,只能是默認訪問權限
  2. 局部內部類不能被外部方法調用
  3. 局部內部類不能訪問非final局部變量在JDK1.7之前,但是可以訪問final變量;在JDK1.8以后,局部內部類也可以訪問非final局部變量

4.靜態嵌套類

  在類中創建的靜態類在Java中稱為靜態嵌套類。它不能訪問非靜態數據成員和方法。它可以由外部類名訪問。

  1. 它可以訪問包括私有的外部類的靜態數據成員。
  2. 靜態嵌套類不能訪問非靜態(實例)數據成員或方法

  靜態嵌套類舉例

class TestOuter1{  
  static int data=30;  
  static class Inner{  
   void msg(){System.out.println("data is "+data);}  
  }  
  public static void main(String args[]){  
  TestOuter1.Inner obj=new TestOuter1.Inner();  
  obj.msg();  
  }  
} 

  在這個例子中,你需要創建靜態嵌套類的實例,因為他含有實例方法msg()。但是你不需要創建外部類的實例,因為嵌套類是靜態的並且靜態的屬性、方法、類在沒有對象情況下可以被訪問

  編譯器生成的代碼:

1 import java.io.PrintStream;  
2 static class TestOuter1$Inner  
3 {  
4 TestOuter1$Inner(){}  
5 void msg(){  
6 System.out.println((new StringBuilder()).append("data is ")  
7 .append(TestOuter1.data).toString());  
8 }    
9 }  

5. 嵌套接口

  在另一個接口或類中聲明的接口稱為嵌套接口。嵌套接口用於對相關接口進行分組,以便它們易於維護。嵌套接口必須由外部接口或類引用。它不能直接訪問。

  嵌套接口要記住的要點

  1. 嵌套接口在接口內聲明時必須是公共的,但是如果在類內聲明,則它可以具有任何訪問修飾符。
  2. 嵌套接口隱式地聲明為靜態的

  嵌套接口在接口內聲明舉例

interface Showable{  
  void show();  
  interface Message{  
   void msg();  
  }  
}  
class TestNestedInterface1 implements Showable.Message{  
 public void msg(){System.out.println("Hello nested interface");}  
  
 public static void main(String args[]){  
  Showable.Message message=new TestNestedInterface1();//upcasting here  
  message.msg();  
 }  
}
  正如您在上面的示例中看到的,我們通過其外部接口Showable訪問Message接口,因為它不能直接訪問。就像房間里的衣櫥一樣,我們不能直接進入衣櫥,因為我們必須先進入房間。在集合的框架中, sun microsystem提供了嵌套接口Entry,Entry是Map的子接口,可以通過Map.Entry訪問

  java編輯器為嵌套接口生成的代碼

public static interface Showable$Message  
{  
  public abstract void msg();  
}

  我們能在接口中定義一個類嗎?

  是的,我們可以在接口中定義一個類,java編譯器將會創建一個靜態嵌套類

原文地址:https://www.javatpoint.com/java-inner-class

 

 

 

 

 

 


免責聲明!

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



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