JDK-5009601 : Bring enum implementation up to date with its spec
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 1.4.0
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2004-03-08
  • Updated: 2017-05-16
  • Resolved: 2004-04-01
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
5.0 b46Fixed
Related Reports
Relates :  
Relates :  
Relates :  
Description
Attached to the CCC proposal corresponding to this bug report is the latest JSR-201 spec draft for enum types (labeled "Preliminary Proposed Final Draft 2").  There are three substantive changes in this draft:

(1)  All enum constructors are implicitly private.  The compiler should implement this behavior.

(2) The use of the abstract and final modifiers on enum types is prohibited.  The compiler should generate a compile-time error if a program uses either of these modifiers on an enum-type.

(3) It is illegal to reflectively instantiate an enum type.  
Constructor.newInstance() will need new checks. (Class.newInstance() should then behave properly as it is implemented in terms of Constructor.newInstance().)

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: tiger-beta2 FIXED IN: tiger-beta2 INTEGRATED IN: tiger-b46 tiger-beta2
14-06-2004

WORK AROUND
11-06-2004

PUBLIC COMMENTS ...
10-06-2004

SUGGESTED FIX src/share/classes/com/sun/tools/javac/parser>sccs sccsdiff -r1.69 -r1.70 Parser.java ------- Parser.java ------- 2167c2167,2168 < ClassDef(mods, name, TypeParameter.emptyList, --- > ClassDef(new Modifiers(mods.flags|Flags.ENUM, mods.annotations), > name, TypeParameter.emptyList, 2213c2214,2215 < F.Modifiers(Flags.ENUM), names.empty, TypeParameter.emptyList, --- > F.Modifiers(Flags.ENUM | Flags.STATIC), > names.empty, TypeParameter.emptyList, src/share/classes/com/sun/tools/javac/code>sccs sccsdiff -r1.4 -r1.5 BoundKind.java ------- BoundKind.java ------- 20c20 < protected BoundKind(String name) { --- > BoundKind(String name) { src/share/classes/com/sun/tools/javac/comp>sccs sccsdiff -r1.109 -r1.110 Enter.java ------- Enter.java ------- 301c301 < c.flags_field = chk.checkFlags(tree.pos, tree.mods.flags, c); --- > c.flags_field = chk.checkFlags(tree.pos, tree.mods.flags, c, tree); src/share/classes/com/sun/tools/javac/comp>sccs sccsdiff -r1.25 -r1.26 MemberEnter.java ------- MemberEnter.java ------- 542c542 < m.flags_field = chk.checkFlags(tree.pos, tree.mods.flags, m); --- > m.flags_field = chk.checkFlags(tree.pos, tree.mods.flags, m, tree); 585c585 < v.flags_field = chk.checkFlags(tree.pos, tree.mods.flags, v); --- > v.flags_field = chk.checkFlags(tree.pos, tree.mods.flags, v, tree); 985c985,990 < flags |= (c.flags() & AccessFlags) | GENERATEDCONSTR; --- > if ((c.flags() & ENUM) != 0 && > types.supertype(c.type).tsym == syms.enumSym) { > // constructors of true enums are private > flags = (flags & ~AccessFlags) | PRIVATE | GENERATEDCONSTR; > } else > flags |= (c.flags() & AccessFlags) | GENERATEDCONSTR; src/share/classes/com/sun/tools/javac/comp>sccs sccsdiff -r1.153 -r1.154 Attr.java ------- Attr.java ------- 2260,2268c2260,2270 < // Enums may not be extended. < if (allowEnums) { < if (st.tsym == syms.enumSym) { < c.flags_field |= Flags.ENUM; < } else if (st.tsym != null && < ((st.tsym.flags_field^c.flags_field) & Flags.ENUM) != 0 && < !target.compilerBootstrap(c)) { < log.error(env.tree.pos, "enum.types.not.extensible"); < } --- > // java.lang.Enum may not be subclassed by a non-enum > if (st.tsym == syms.enumSym && > ((c.flags_field & Flags.ENUM) == 0) ) > log.error(env.tree.pos, "enum.no.subclassing"); > > // Enums may not be extended by source-level classes > if (st.tsym != null && > ((st.tsym.flags_field & Flags.ENUM) != 0) && > ((c.flags_field & Flags.ENUM) == 0) && > !target.compilerBootstrap(c)) { > log.error(env.tree.pos, "enum.types.not.extensible"); src/share/classes/com/sun/tools/javac/comp>sccs sccsdiff -r1.116 -r1.117 Check.java ------- Check.java ------- 593c593 < long checkFlags(int pos, long flags, Symbol sym) { --- > long checkFlags(int pos, long flags, Symbol sym, Tree tree) { 606,608c606,615 < if (sym.name == names.init) < mask = ConstructorFlags; < else if ((sym.owner.flags_field & INTERFACE) != 0) --- > if (sym.name == names.init) { > if ((sym.owner.flags_field & ENUM) != 0) { > // enum constructors cannot be declared public or > // protected and must be implicitly or explicitly > // private > implicit = PRIVATE; > mask = PRIVATE; > } else > mask = ConstructorFlags; > } else if ((sym.owner.flags_field & INTERFACE) != 0) 627,628c634,635 < // Nested interfaces are always STATIC (Spec ???) < if ((flags & INTERFACE) != 0) implicit = STATIC; --- > // Nested interfaces and enums are always STATIC (Spec ???) > if ((flags & (INTERFACE | ENUM)) != 0 ) implicit = STATIC; 634,635c641,647 < // Enums are always STATIC < if ((flags & ENUM) != 0) implicit |= STATIC; --- > > if ((flags & ENUM) != 0) { > // enums can't be declared abstract or final > mask &= ~(ABSTRACT | FINAL); > implicit |= computeImplicitEnumClassFlags(tree); > > } 677a690,745 > > /** Determine if this enum should be implicitly final or abstract. > * > * If the enum has no specialized enum contants, it is final. > * > * If the enum does have specialized enum contants, it is > * <i>not</i> final. > * > * If the enum has specialized constants and some methods of the > * enum are abstract, it is marked abstract. > */ > private long computeImplicitEnumClassFlags(Tree tree) { > long implicitFlags = 0; > > try { > class SpecialTreeVisitor extends Tree.Visitor { > boolean specialized; > boolean Abstract; > SpecialTreeVisitor() { > this.specialized = false; > this.Abstract = false; > }; > > public void visitTree(Tree tree) { /* no-op */ } > > public void visitVarDef(VarDef tree) { > if ((tree.mods.flags & ENUM) != 0) { > if (tree.init instanceof NewClass && > ((NewClass)tree.init).def != null) { > specialized = true; > // System.out.println("Specialized tree: " + tree); > } > } > } > > public void visitMethodDef(MethodDef tree) { > if ((tree.mods.flags & ABSTRACT) != 0) > Abstract = true; > } > > } > > SpecialTreeVisitor sts = new SpecialTreeVisitor(); > ClassDef cdef = (ClassDef) tree; > for(Tree defs: cdef.defs) > defs.accept(sts); > > implicitFlags = (!sts.specialized ? > FINAL: > (sts.Abstract ? ABSTRACT : 0L)); > > } catch (ClassCastException cce) {} > > return implicitFlags; > } > src/share/classes/java/lang/reflect>sccs sccsdiff -r1.44 -r1.45 Constructor.java ------- Constructor.java ------- 389c389,390 < * parameter type by a method invocation conversion. --- > * parameter type by a method invocation conversion; if > * this constructor pertains to an enum type. 409a411,412 > if ((clazz.getModifiers() & Modifier.ENUM) != 0) > throw new IllegalArgumentException("Cannot reflectively create enum objects"); ###@###.### 2004-03-29
29-03-2004

EVALUATION Will aim for beta2. ###@###.### 2004-03-08
08-03-2004