Java 11在嵌套類方面主要關注的是通過JEP 181來改進訪問控制,解決之前版本中存在的權限不一致問題。
下面先來看下嵌套類的使用:
靜態嵌套類(Static Nested Class)
- 定義:靜態嵌套類(也稱為靜態內部類)是定義在另一個類中的類,并且使用static關鍵字修飾。
- 訪問權限:靜態嵌套類只能訪問外部類的靜態成員(靜態變量、靜態方法和靜態嵌套類),不能訪問外部類的非靜態成員。
- 實例化:靜態嵌套類不需要外部類對象即可實例化,可以直接通過類名來創建實例。
- 用途:靜態嵌套類通常用于組織工具類、輔助類等與外部類緊密相關的類,但不依賴于外部類的非靜態狀態。
靜態嵌套類使用static
關鍵字修飾,可以獨立于外部類實例使用。由于它是靜態的,因此不能直接訪問外部類的非靜態成員。
package com.morris.java11;/*** 靜態嵌套類(Static Nested Class)的使用*/
public class StaticNestedClassDemo {// 靜態嵌套類public static class StaticNestedClass {public void display() {System.out.println("Inside static nested class");}}public static void main(String[] args) {// 創建靜態嵌套類的實例StaticNestedClassDemo.StaticNestedClass nested = new StaticNestedClassDemo.StaticNestedClass();nested.display();}
}
內部類(Inner Class)
- 定義:內部類(也稱為非靜態嵌套類)是定義在另一個類中的類,不使用static關鍵字修飾。
- 訪問權限:內部類可以訪問外部類的所有成員(靜態和非靜態成員),包括私有成員。
- 實例化:內部類需要外部類對象才能實例化,通常通過外部類對象來創建內部類實例,或者在內部類中通過this或外部類名.this來引用外部類對象。
- 用途:內部類常用于實現回調、監聽器、閉包等需要訪問外部類狀態的場景,也可以用于組織緊密相關的類,提高代碼封裝性。
非靜態嵌套類(內部類)沒有使用 static
修飾,需要通過外部類的實例來創建。它可以直接訪問外部類的所有成員,包括私有成員。
package com.morris.java11;/*** 內部類(Inner Class)的使用*/
public class InnerClassDemo {private String outerField = "Outer field value";// 內部類public class InnerClass {public void display() {System.out.println("Inside inner class");System.out.println("Accessing outer class field: " + outerField);}}public static void main(String[] args) {InnerClassDemo outer = new InnerClassDemo();// 創建內部類的實例InnerClassDemo.InnerClass inner = outer.new InnerClass();inner.display();}
}
匿名內部類(Anonymous Inner Class)
匿名內部類是內部類的一種特殊形式,它沒有類名,通常在實現接口或繼承類時直接定義在方法內部。匿名內部類通常用于一次性的操作,比如創建一個線程或實現某個接口時。
匿名類是沒有名字的局部類,通常用于實現接口或繼承類的臨時實例。
package com.morris.java11;/*** 匿名內部類(Anonymous Inner Class)的使用*/
public class AnonymousInnerClass {private String outerField = "Outer field value";public void methodWithAnonymousClass() {// 匿名類實現接口Runnable runnable = new Runnable() {@Overridepublic void run() {System.out.println("Inside anonymous class");System.out.println("Accessing outer class field: " + outerField);}};runnable.run();}public static void main(String[] args) {AnonymousInnerClass outer = new AnonymousInnerClass();outer.methodWithAnonymousClass();}
}
局部內部類(Local Inner Class)
局部內部類定義在外部類的方法內部,它的作用域僅限于該方法。局部內部類只能訪問該方法中的final局部變量(從Java 8開始,這個限制放寬了,但局部變量必須是事實上不可變的)。
局部類是在方法、構造器或作用域內部定義的類。它只能在定義它的作用域中使用。
package com.morris.java11;/*** 局部內部類Local Inner Class的使用*/
public class LocalInnerClassDemo {private String outerField = "Outer field value";public void methodWithLocalClass() {// 局部內部類class LocalClass {public void display() {System.out.println("Inside local class");System.out.println("Accessing outer class field: " + outerField);}}LocalClass local = new LocalClass();local.display();}public static void main(String[] args) {LocalInnerClassDemo outer = new LocalInnerClassDemo();outer.methodWithLocalClass();}
}
嵌套類API的使用
Class.isNestmateOf()用于確定一個類是否是另一個類的嵌套成員或與其在同一嵌套類中。
Class.getNestHost()用于獲取嵌套類的宿主類(nest host)。
package com.morris.java11;import java.util.Arrays;
import java.util.Set;
import java.util.stream.Collectors;/*** 嵌套類API的使用*/
public class NestClassApiDemo {public static void main(String[] args) {boolean isNestMate = NestClassApiDemo.class.isNestmateOf(NestClassApiDemo.Inner.class);boolean nestHost = NestClassApiDemo.Inner.class.getNestHost() == NestClassApiDemo.class;System.out.println(isNestMate); // trueSystem.out.println(nestHost); // trueSet<String> nestedMembers = Arrays.stream(NestClassApiDemo.Inner.class.getNestMembers()).map(Class::getName).collect(Collectors.toSet());System.out.println(nestedMembers); // [com.morris.java11.NestClassApiDemo, com.morris.java11.NestClassApiDemo$Inner]}public static class Inner{}
}