JDK-8282795 : EnumSet should be a sealed class
  • Type: CSR
  • Component: core-libs
  • Sub-Component: java.util:collections
  • Priority: P4
  • Status: Closed
  • Resolution: Approved
  • Fix Versions: 19
  • Submitted: 2022-03-08
  • Updated: 2022-03-12
  • Resolved: 2022-03-10
Related Reports
CSR :  
Description
Summary
-------
`java.util.EnumSet` will be marked as a `sealed` class with the current existing (package private) `java.util.JumboEnumSet` and `java.util.RegularEnumSet` as the sole permitted classes.

Problem
-------
`java.util.EnumSet` is a `public abstract` class which has a package private constructor. The only 2 sub-classes are the `JumboEnumSet` and the `RegularEnumSet`, both of which have a package private class access modifier. Effectively, these are the only 2 sub-classes within the JDK for the `java.util.EnumSet`. No other sub-classes are intended for the `EnumSet`. Hence, marking it as `sealed` and also permitting only these 2 sub-classes allows the JDK code to take advantage of the compiler checks that will prevent any unexpected sub-classes to be introduced.


Solution
--------
The `EnumSet` class will be marked as `sealed` and `permits JumboEnumSet, RegularEnumSet`. Both the `JumboEnumSet` and `RegularEnumSet` will be marked as `final`.

Specification
-------------
```
diff --git a/src/java.base/share/classes/java/util/EnumSet.java b/src/java.base/share/classes/java/util/EnumSet.java
index ee475ba338a..3776cedd5bb 100644
--- a/src/java.base/share/classes/java/util/EnumSet.java
+++ b/src/java.base/share/classes/java/util/EnumSet.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -76,8 +76,8 @@ import jdk.internal.access.SharedSecrets;
  * @since 1.5
  * @see EnumMap
  */
-public abstract class EnumSet<E extends Enum<E>> extends AbstractSet<E>
-    implements Cloneable, java.io.Serializable
+public abstract sealed class EnumSet<E extends Enum<E>> extends AbstractSet<E>
+    implements Cloneable, java.io.Serializable permits JumboEnumSet, RegularEnumSet
 {
     // declare EnumSet.class serialization compatibility with JDK 8
     @java.io.Serial
diff --git a/src/java.base/share/classes/java/util/JumboEnumSet.java b/src/java.base/share/classes/java/util/JumboEnumSet.java
index f80e5056803..126fc077b6c 100644
--- a/src/java.base/share/classes/java/util/JumboEnumSet.java
+++ b/src/java.base/share/classes/java/util/JumboEnumSet.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,7 +33,7 @@ package java.util;
  * @since 1.5
  * @serial exclude
  */
-class JumboEnumSet<E extends Enum<E>> extends EnumSet<E> {
+final class JumboEnumSet<E extends Enum<E>> extends EnumSet<E> {
     @java.io.Serial
     private static final long serialVersionUID = 334349849919042784L;
 
diff --git a/src/java.base/share/classes/java/util/RegularEnumSet.java b/src/java.base/share/classes/java/util/RegularEnumSet.java
index 1deda8a2935..f06adcbf692 100644
--- a/src/java.base/share/classes/java/util/RegularEnumSet.java
+++ b/src/java.base/share/classes/java/util/RegularEnumSet.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,7 +33,7 @@ package java.util;
  * @since 1.5
  * @serial exclude
  */
-class RegularEnumSet<E extends Enum<E>> extends EnumSet<E> {
+final class RegularEnumSet<E extends Enum<E>> extends EnumSet<E> {
     @java.io.Serial
     private static final long serialVersionUID = 3411599620347842686L;
     /**
```
Comments
[~jpai], thanks for checking.
12-03-2022

I checked the generated javadoc for the EnumSet class. The output doesn't differ from what it was before this change.
11-03-2022

I had noticed that the (internal) JumboEnumSet and RegularEnumSet had a "@serial exclude" in their javadoc. I hadn't paid attention to the now sealed EnumSet. I'll run a few checks on the generated javadoc today and make sure all is fine.
11-03-2022

Looks fine. Since all the {$Foo}Enum sets in question have their serialVersionUID fields set (HT JDK-7028133) and the use of proxies, there shouldn't be any serialization complications. I suggest double-checking the javadoc output with the change. Presumably it should *not* change since the subclasses are package-private. If it does change, a javadoc bug may be in order. Moving to Approved.
10-03-2022