jdk15至17——sealed密封关键字

sealed关键字是从jdk15开始预览,直到jdk17成为正式版,可以对继承父类和实现接口进行更加细粒度的限制,之前的限制也只有final用于禁止继承,默认包权限限制在同一个包内,sealed密封类/接口可以明确指定哪些类可以进行继承和实现;

跟sealed相关的关键字除了之前的final,还有新增的non-sealed和permits:

  • permits:用于明确指定允许继承的子类和实现类,且不能使用匿名类动态类,书写位置在extends/implements后面(大概是放最后面);
  • sealed:指定类/接口为密封类/接口,后面必须使用permits指定子类/实现类;
  • final:指定类为最终类,不能被继承;
  • non-sealed:解除密封性,指定为普通类关系;

sealed可以修饰类也可以修饰接口,密封类的子类必须使用sealed、final、non-sealed其中之一修饰,sealed修饰的子类继续密封,后面继续使用permits指定,final修饰的子类为最终类,不能被继承,non-sealed修饰的子类密封性解除,后续可以当普通类使用;

permits指定的允许类为直接指定,不具有传递性;

代码展示:

package test;

public class MainTest {
	
	//密封类A只能被A1,A2,A3继承
	public sealed class A permits A1, A2, A3 {}
	//A1为final类,不能继续被继承
	public final class A1 extends A {}
	//A2使用non-sealed修饰,解除密封限制可被任何类继承
	public non-sealed class A2 extends A {}
	//A3仍为密封类,需要继续用permits指定可继承类
	public sealed class A3 extends A permits B {}
	
	public final class B extends A3 {}
	
//	public final class A4 extends A {}	//报错,A4未被A指定未可继承类
	
	public class C extends A2 {}	//任何类都可继承A2
	
	public static void main(String[] args) {
		
	}
	
}

另外,sealed类和子类/实现类,可以在同一个包下,也可以在不同的包下,但是必须在同一个模块下,如果使用未命名的模块,则必须在同一个包里;

需要在不同包里使用时需要建一个命名的模块:

jdk15至17——sealed密封关键字_第1张图片

另外,由于record类型最后编译成final类并且不支持继承和被继承,所以可以跟sealed接口一起使用,使代码更简介:

package test;

public class MainTest {
	
	public sealed interface A permits B, C {
		public void fun();
	}

	public record B(String s) implements A {
		@Override
		public void fun() {
			System.out.println("B fun:" + s);
		}
	}

	public record C(int i) implements A {
		@Override
		public void fun() {
			System.out.println("C fun:" + i);
		}
	}
	
	public static void main(String[] args) {
		A b = new B("abc");
		A c = new C(321);
		b.fun();
		c.fun();
	}
	
}

你可能感兴趣的:(JDK特性,jdk特性)