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{}
}