[Java Spec Report] JSR 201 enum comments
Eric Blake <[email protected]> Fri, 07 May 2004 09:01:21 -0600
| Newsgroups | gmane.comp.java.spec-report |
|---|---|
| Message-ID | <[email protected]> |
A few questions about enums:
First, JLS 8.5.2 states that the static keyword may only modify member types
of a non-inner class, and JLS 8.1.2 states that inner classes may not declare
static members. The public draft states "Enum classes are implicitly static",
and allow a person to redundantly list the static modifier when declaring an
enum class. Note that the current javac beta version allows an enum in an
inner class, but only when the implicit static modifier is not redundantly
specified:
class C {
class Inner {
enum E1 {}
// static enum E2 {} // compile error
}
}
It makes sense to allow enums anywhere. However, because the JLS never
allowed for a static member class inside an inner class, there are a lot of
specification gaps that will need to be filled in before having an enum inside
an inner class is 100% specified. Is this your intention? Or is javac in
error for allowing the above?
Note that allowing an enum in an inner class makes static contexts much more
pervasive. Previously, the only time I could construct a static context
inside an inner class was the following contorted code (similar to what I have
inserted into the Jacks compiler test suite):
class C {
class Inner {
Inner(Object o) {}
Inner() {
this(new Object() { // static context embedded in inner class
});
}
}
}
Also, if you do decide that allowing static enums inside an inner class make
sense, then why not allow any static member type (interfaces or static
classes) in an inner class? A static member type has different semantics than
a static member variable or method, and I have always found it odd that the
current JLS has a one-way gate - you can have as many layers of all static or
all inner classes as you want, but as soon as you switch from static to inner,
all deeper layers must be inner. I think it would make more sense for the
notion of a class being static or not be orthogonal to what its enclosing
class is, such that the following becomes legal:
class C {
class Inner {
static class Static {}
}
}
My second question:
Are enums legal as local classes? Your do not list a grammar change to permit
it. But, similar to the behavior in my previous question, javac currently
allows a local enum, but only if the static keyword is left implicit.
class C {
void m() {
enum E1 {}
// static enum E2 {} // compile error
}
}
Also, I think it would be nice to allow all types as local types; currently,
annotation types and interfaces are prohibited as inner classes.
Third question:
In C++, enum constants are brought into the scope that declared the overall
enum. In Java, this does not make much sense at for package level enums (how
would you tell whether p.A is a class vs. shorthand for p.E.A brought into the
same scope as p.E?), but would be reasonable for member enums. This is
particularly true for enums inside an anonymous class or local enums (if you
decide that both of these are legal, from my first two questions) - in these
cases, there is no way to use static imports to otherwise bring those simple
names into scope, and it can be annoying to always have to type a qualified
name. For example:
package p;
import static p.C.E2.*; // bring E2's enum constants into scope
class C {
enum E1 {
a,
}
E1 e1a = a; // currently illegal, a is not in scope
// but since E1 is a member, this would be legal if you bring all enum
// constants into the same scope that declared E1
E1 e1b = E1.a; // legal, but verbose
enum E2 {
b;
}
E2 e2a = b; // legal because of the static import
E2 e2b = E2.b; // legal
Object o = new Object() {
enum E3 {
c,; // cute syntax, allowed by the public draft
}
E3 e3a = c; // no way to make this legal with static import
// but having it legal would better match C++
E3 e3b = E3.c;
};
void m() {
enum E4 {
d
}
E4 e4a = d; // again, static import won't work
// but it would sure be nice for d to be in scope in m()
E4 e4b = E4.d;
}
}
Fourth question:
What is the correct grammar for enums? Your listed grammar has several flaws,
because it does not state where annotations may be placed on an EnumConstant,
and because it lists EnumConst: Identifier which is ambiguous with the
existing ConstantExpression grammar rule, and fails to permit qualified names.
It seems like the current javac implementation allows annotations to be
specified per EnumConstant, which is unlike other field declarations where an
annotation applies to every VariableDeclaratorId in the comma-separated list:
enum E {
@A One,
@B Two;
@C int Three, Four; // both Three and Four are annotated by C
}
It would be nice for consistency if you were to extend the no-args constructor
elided parenthesis syntactic sugar to other contexts. Method calls will
always need the () if there are no arguments (since methods and fields are
different namespaces, the () determines which namespace to use), but
constructor calls could be simplified in the no-arg case (because the new
keyword implies a constructor context, just as for EnumConstant declarations).
In other words, I would like the following example to be legal:
class C {
enum E {
A, // short for A(), allowed by public draft
B(),
C {}, // short for C() {}, allowed by public draft
D() {}
}
void m() {
Object o;
o = new C; // short for new C(), currently illegal
o = new C();
o = new C {}; // short for new C() {}, currently illegal
o = new C() {};
}
C() {
super; // questionable whether this should be short for super()
}
}
And while I'm asking for consistent syntactic sugar, this next request better
belongs in JSR 175, but why not extend the single-member-array brace elision
syntactic sugar to the full language? In other words:
class C {
@interface I {
int[] value();
}
@I(1) int a; // short for @I(value={1}), allowed by JSR 175
@I({2}) int b;
int[] c = 3; // short for int[] c = {3}, currently illegal
int[] d = {4};
int[] e = new int[] 5; // short for new int[] {5}, currently illegal
int[] f = new int[] {6};
int[] m(int[] a, int b) { return a; }
int[] n(int... a) { return a; }
int[] g = m(1, 2); // short for m(new int[] {1}, 2), currently illegal
int[] h = n(1); // short for n(new int[] {1}), allowed by varargs
int[] i = m(new int[] {1}, 2);
int[] j = n(new int[] {1});
}
Last question (for now):
Would it be reasonable to add a syntax for anonymous enums? This depends on
the answer to my third question, but I could see the utility of some variation
of the following:
class C {
enum state(STARTED) { STOPPED, STARTED };
void start() { state = STARTED; }
void stop() { state = STOPPED; }
}
Here, the idea is that 'enum' identifierA '(' ( identifierB | 'null' ) ')'
EnumBody introduces identifierA as a variable with anonymous type, and
initialized to the enum constant identifierB declared within the anonymous
EnumBody (rather than introducing identifierA as the name of the enum type).
An initialization for identifierA is mandatory, but can be null (since any
enum variable can also hold a null reference). This approach relies on the
enum constants of the anonymous enum being brought into the scope that
declared identifierA (otherwise, the variable is useless, because it cannot be
reassigned). It seems a little odd to be referring to the enum constants
before their declaration, but since Java types declarations don't end in ';'
(unlike C++), we can't use the C++ syntax of declaring a variable of an
anonymous enum type by listing the variable between the closing '}' and ';'.
This idea can be extended to a sequence of variables sharing the anonymous type:
class C {
enum a(A), b(B) { A, B, };
}
--
Someday, I might put a cute statement here.
Eric Blake [email protected]
------------------------ Yahoo! Groups Sponsor ---------------------~-->
Yahoo! Domains - Claim yours for only $14.70
http://us.click.yahoo.com/Z1wmxD/DREIAA/yQLSAA/5cFolB/TM
---------------------------------------------------------------------~->
To unsubscribe from this mailing list, send an email to:
[email protected]
Yahoo! Groups Links
<*> To visit your group on the web, go to:
http://groups.yahoo.com/group/java-spec-report/
<*> To unsubscribe from this group, send an email to:
[email protected]
<*> Your use of Yahoo! Groups is subject to:
http://docs.yahoo.com/info/terms/