Java內部類

2019-10-16 22:23:27

在Java中,就像方法一樣,類的變數也可以將另一個類作為它的成員。 在Java中允許在一個類中編寫另一個類。 在其中編寫的類稱為巢狀類,而儲存內部類的類稱為外部類。

語法

以下是編寫巢狀類的語法。 這裡,類OuterDemo是外部類,而類InnerDemo是巢狀類。

class OuterDemo {
   class InnerDemo {
   }
}

巢狀類分為兩種型別 -

  • 非靜態巢狀類 - 這些是類的非靜態成員。
  • 靜態巢狀類 - 這些是類的靜態成員。

嵌套類

1. 內部類(非靜態巢狀類)

內部類是Java中的安全機制。 我們知道一個類不能與private存取修飾符關聯,但如果將該類作為其他類的成員,那麼內部類可以變為private。 這也用於存取類的私有成員。

內部類有三種型別,具體取決於定義它們的方式和位置。它們分別是 -

  • 內部類
  • 方法-區域性內部類
  • 匿名內部類

1.1. 內部類

建立內部類非常簡單,只需要在一個類中編寫一個類。 與類不同,內部類可以是私有的,當將內部類宣告為private,就無法從類外部的物件存取它。

以下是建立內部類並存取它的程式。 在範例中,將內部類設為private,並通過方法存取類。

範例

class OuterDemo {
   int num;

   // 內部類
   private class InnerDemo {
      public void print() {
         System.out.println("This is an inner class");
      }
   }

   // 從內部方法存取他的內部類
   void display_Inner() {
      InnerDemo inner = new InnerDemo();
      inner.print();
   }
}

public class Myclass {

   public static void main(String args[]) {
      // 範例化外部類
      OuterDemo outer = new OuterDemo();

      // 存取 display_Inner()方法。
      outer.display_Inner();
   }
}

在範例中OuterDemo是外部類,InnerDemo是內部類,display_Inner()是在其中範例化內部類的方法,並且這個方法是從main方法呼叫的。

編譯並執行上述程式,將得到以下結果 -

This is an inner class.

存取私有成員

如前所述,內部類也用於存取類的私有成員。 假設,一個類想要讓私有成員存取,可從內部類中的方法返回私有成員。

要範例化內部類,最初必須範例化外部類。 此後,使用外部類的物件存取內部類,以下是範例化內部類的方法。

OuterDemo outer = new OuterDemo();
OuterDemo.InnerDemo inner = outer.new InnerDemo();

以下程式顯示如何使用內部類存取類的私有成員。

class OuterDemo {
   // 外部類的私有變數
   private int num = 175;  

   // 內部類
   public class InnerDemo {
      public int getNum() {
         System.out.println("This is the getnum method of the inner class");
         return num;
      }
   }
}

public class My_class2 {

   public static void main(String args[]) {
      // 範例化外部類
      OuterDemo outer = new OuterDemo();

      // 範例化內部類
      OuterDemo.InnerDemo inner = outer.new InnerDemo();
      System.out.println(inner.getNum());
   }
}

編譯並執行上述程式,將得到以下結果 -

This is the getnum method of the inner class: 175

1.2. 方法-區域性內部類

在Java中,可以在方法中編寫一個類,這將是一個區域性型別。與區域性變數一樣,內部類的範圍在方法中受到限制。

方法區域性內部類只能在定義內部類的方法中範例化。 以下程式顯示了如何使用方法區域性內部類。

範例

public class Outerclass {
   // 外部類的範例方法
   void my_Method() {
      int num = 23;

      // 方法區域性內部類
      class MethodInnerDemo {
         public void print() {
            System.out.println("This is method inner class "+num);       
         }   
      } // end of inner class

      // 存取內部類
      MethodInnerDemo inner = new MethodInnerDemo();
      inner.print();
   }

   public static void main(String args[]) {
      Outerclass outer = new Outerclass();
      outer.my_Method();
   }
}

編譯並執行上述程式,將得到以下結果 -

This is method inner class 23

1.3. 匿名內部類

宣告沒有類名的內部類稱為匿名內部類。 在匿名內部類中,同時宣告併範例化內部類。 通常,只要需要覆蓋類或介面的方法,就會使用它們。 匿名內部類的語法如下 -

語法

AnonymousInner an_inner = new AnonymousInner() {
   public void my_method() {
      ........
      ........
   }   
};

以下程式顯示如何使用匿名內部類覆蓋類的方法。

abstract class AnonymousInner {
   public abstract void mymethod();
}

public class Outer_class {

   public static void main(String args[]) {
      AnonymousInner inner = new AnonymousInner() {
         public void mymethod() {
            System.out.println("This is an example of anonymous inner class");
         }
      };
      inner.mymethod();    
   }
}

編譯並執行上述程式,將得到以下結果 -

This is an example of anonymous inner class

以同樣的方式,可以使用匿名內部類覆蓋具體類的方法以及介面。

2. 匿名內部類作為引數

通常,如果方法接受介面,抽象類或具體類的物件,那麼可以實現介面,擴充套件抽象類,並將物件傳遞給方法。如果它是一個類,那麼可以直接將它傳遞給方法。

在這三種情況下,都可以將匿名內部類傳遞給方法。 以下是將匿名內部類作為方法引數傳遞的語法 -

obj.my_Method(new My_Class() {
   public void Do() {
      .....
      .....
   }
});

以下程式演示如何將匿名內部類作為方法引數傳遞。

// 定義介面
interface Message {
   String greet();
}

public class Myclass {
   // 接受介面 Message 物件的方法
   public void displayMessage(Message m) {
      System.out.println(m.greet() +
         ", This is an example of anonymous inner class as an argument");  
   }

   public static void main(String args[]) {
      // 範例化類
      Myclass obj = new Myclass();

      // 傳遞匿名內部類作為引數
      obj.displayMessage(new Message() {
         public String greet() {
            return "Hello";
         }
      });
   }
}

編譯並執行上述程式,將得到以下結果 -

Hello, This is an example of anonymous inner class as an argument

3. 靜態巢狀類

靜態內部類是巢狀類,它是外部類的靜態成員。 可以使用其他靜態成員在不範例化外部類的情況下存取它。 就像靜態成員一樣,靜態巢狀類無法存取外部類的範例變數和方法。 靜態巢狀類的語法如下 -

class MyOuter {
   static class Nested_Demo {
   }
}

範例化靜態巢狀類與範例化內部類略有不同。 以下程式顯示了如何使用靜態巢狀類。

範例

public class Outer {
   static class Nested_Demo {
      public void my_method() {
         System.out.println("This is my nested class");
      }
   }

   public static void main(String args[]) {
      Outer.Nested_Demo nested = new Outer.Nested_Demo();     
      nested.my_method();
   }
}

編譯並執行上述程式,將得到以下結果 -

This is my nested class