diff --git a/src/java/org/apache/commons/lang/enum/Enum.java b/src/java/org/apache/commons/lang/enum/Enum.java index 7d55b2c75..6162b9021 100644 --- a/src/java/org/apache/commons/lang/enum/Enum.java +++ b/src/java/org/apache/commons/lang/enum/Enum.java @@ -214,13 +214,60 @@ * *
The code above will work on JDK 1.2. If JDK1.3 and later is used, * the subclasses may be defined as anonymous.
+ * + *Care must be taken with class loading when defining a static nested class + * for enums. The static nested class can be loaded without the surrounding outer + * class being loaded. This can result in an empty list/map/iterator being returned. + * One solution is to define a static block that references the outer class where + * the constants are defined. For example:
+ * + *+ * public final class Outer { + * public static final BWEnum BLACK = new BWEnum("Black"); + * public static final BWEnum WHITE = new BWEnum("White"); + * + * // static nested enum class + * public static final class BWEnum extends Enum { + * + * static { + * // explicitly reference BWEnum class to force constants to load + * Object obj = Outer.BLACK; + * } + * + * // ... other methods omitted + * } + * } + *+ * + *
Although the above solves the problem, it is not recommended. The best solution + * is to define the constants in the enum class, and hold references in the outer class: + * + *
+ * public final class Outer { + * public static final BWEnum BLACK = BWEnum.BLACK; + * public static final BWEnum WHITE = BWEnum.WHITE; + * + * // static nested enum class + * public static final class BWEnum extends Enum { + * // only define constants in enum classes - private if desired + * private static final BWEnum BLACK = new BWEnum("Black"); + * private static final BWEnum WHITE = new BWEnum("White"); + * + * // ... other methods omitted + * } + * } + *+ * + *
For more details, see the 'Nested' test cases.
+ *
* @author Apache Avalon project
* @author Stephen Colebourne
* @author Chris Webb
* @author Mike Bowler
* @since 1.0
- * @version $Id: Enum.java,v 1.22 2003/09/07 14:32:34 psteitz Exp $
+ * @version $Id: Enum.java,v 1.23 2003/11/29 15:03:54 scolebourne Exp $
*/
public abstract class Enum implements Comparable, Serializable {
diff --git a/src/test/org/apache/commons/lang/enum/EnumTest.java b/src/test/org/apache/commons/lang/enum/EnumTest.java
index 226b60478..2dcdcb59b 100644
--- a/src/test/org/apache/commons/lang/enum/EnumTest.java
+++ b/src/test/org/apache/commons/lang/enum/EnumTest.java
@@ -53,6 +53,8 @@
*/
package org.apache.commons.lang.enum;
+import java.util.ArrayList;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -67,7 +69,7 @@
* Test cases for the {@link Enum} class.
*
* @author Stephen Colebourne
- * @version $Id: EnumTest.java,v 1.11 2003/08/18 02:22:27 bayard Exp $
+ * @version $Id: EnumTest.java,v 1.12 2003/11/29 15:03:54 scolebourne Exp $
*/
public final class EnumTest extends TestCase {
@@ -132,7 +134,7 @@ public void testIterator() {
}
public void testList() {
- List list = ColorEnum.getEnumList();
+ List list = new ArrayList(ColorEnum.getEnumList());
assertNotNull(list);
@@ -146,19 +148,17 @@ public void testList() {
}
public void testMap() {
- Map map = ColorEnum.getEnumMap();
+ Map map = new HashMap(ColorEnum.getEnumMap());
assertNotNull(map);
-
- assertEquals( map.keySet().size(),
- ColorEnum.getEnumList().size());
-
assertTrue(map.containsValue(ColorEnum.RED));
assertTrue(map.containsValue(ColorEnum.GREEN));
assertTrue(map.containsValue(ColorEnum.BLUE));
assertSame(ColorEnum.RED, map.get("Red"));
assertSame(ColorEnum.GREEN, map.get("Green"));
assertSame(ColorEnum.BLUE, map.get("Blue"));
+ assertEquals( map.keySet().size(),
+ ColorEnum.getEnumList().size());
}
public void testGet() {
@@ -415,4 +415,54 @@ public void testExtended3Map() {
assertSame(Extended3Enum.DELTA, map.get("Delta"));
}
+ //-----------------------------------------------------------------------
+ public void testNested() {
+ List list = new ArrayList(Nest.ColorEnum.getEnumList());
+ assertEquals(3, list.size()); // all is well
+ Iterator it = list.iterator();
+ assertSame(Nest.ColorEnum.RED, it.next());
+ assertSame(Nest.ColorEnum.GREEN, it.next());
+ assertSame(Nest.ColorEnum.BLUE, it.next());
+ // This nesting works because the enum constants are defined in the SAME
+ // class as the getEnumList(). It just acts as a normal enum.
+ }
+
+ public void testNestedBroken() {
+ List list = new ArrayList(NestBroken.ColorEnum.getEnumList());
+ assertEquals(0, list.size()); // no enums!!!
+ // this is BROKEN because the enum constants are defined in a DIFFERENT
+ // class from getEnumList(). Once NestBroken class is referenced,
+ // and thus class loaded with its enum constants, the getEnumList works:
+ new NestBroken();
+ list = new ArrayList(NestBroken.ColorEnum.getEnumList());
+ assertEquals(3, list.size()); // all is well!!!
+ Iterator it = list.iterator();
+ assertSame(NestBroken.RED, it.next());
+ assertSame(NestBroken.GREEN, it.next());
+ assertSame(NestBroken.BLUE, it.next());
+ }
+
+ public void testNestedLinked() {
+ List list = new ArrayList(NestLinked.ColorEnum.getEnumList());
+ assertEquals(3, list.size()); // all is well
+ Iterator it = list.iterator();
+ assertSame(NestLinked.RED, it.next());
+ assertSame(NestLinked.GREEN, it.next());
+ assertSame(NestLinked.BLUE, it.next());
+ // This nesting works because a static block in the enum class forces a
+ // class load of the outer class which defines the enum constants.
+ }
+
+ public void testNestedReferenced() {
+ List list = new ArrayList(NestReferenced.ColorEnum.getEnumList());
+ assertEquals(3, list.size()); // all is well
+ Iterator it = list.iterator();
+ assertSame(NestReferenced.RED, it.next());
+ assertSame(NestReferenced.GREEN, it.next());
+ assertSame(NestReferenced.BLUE, it.next());
+ // This nesting works because the enum constants are actually defined in
+ // the SAME class as the getEnumList(). The references in the outer class
+ // are just extra references.
+ }
+
}
diff --git a/src/test/org/apache/commons/lang/enum/Nest.java b/src/test/org/apache/commons/lang/enum/Nest.java
new file mode 100644
index 000000000..a8fbacc4f
--- /dev/null
+++ b/src/test/org/apache/commons/lang/enum/Nest.java
@@ -0,0 +1,100 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowledgement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgement may appear in the software itself,
+ * if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ * Foundation" must not be used to endorse or promote products derived
+ * from this software without prior written permission. For written
+ * permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ *
+ * The class loader sees the two classes here as independent - the enum
+ * class is nested, not an inner class. Calling getEnumList() on ColorEnum
+ * will return an empty list, unless and until the NestBroken class is
+ * referenced.
+ *
+ * @author Stephen Colebourne
+ * @version $Id: NestBroken.java,v 1.1 2003/11/29 15:03:54 scolebourne Exp $
+ */
+
+public final class NestBroken {
+
+ public static final ColorEnum RED = new ColorEnum("Red");
+ public static final ColorEnum GREEN = new ColorEnum("Green");
+ public static final ColorEnum BLUE = new ColorEnum("Blue");
+
+ public NestBroken() {
+ super();
+ }
+
+ public static final class ColorEnum extends Enum {
+
+ private ColorEnum(String color) {
+ super(color);
+ }
+
+ public static ColorEnum getEnum(String color) {
+ return (ColorEnum) getEnum(ColorEnum.class, color);
+ }
+
+ public static Map getEnumMap() {
+ return getEnumMap(ColorEnum.class);
+ }
+
+ public static List getEnumList() {
+ return getEnumList(ColorEnum.class);
+ }
+
+ public static Iterator iterator() {
+ return iterator(ColorEnum.class);
+ }
+ }
+}
diff --git a/src/test/org/apache/commons/lang/enum/NestLinked.java b/src/test/org/apache/commons/lang/enum/NestLinked.java
new file mode 100644
index 000000000..97ca17c17
--- /dev/null
+++ b/src/test/org/apache/commons/lang/enum/NestLinked.java
@@ -0,0 +1,111 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowledgement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgement may appear in the software itself,
+ * if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ * Foundation" must not be used to endorse or promote products derived
+ * from this software without prior written permission. For written
+ * permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * static{}
block is
+ * needed to ensure that the enum constants are created before the
+ * static methods on the ColorEnum are used.
+ *
+ * The class loader sees the two classes here as independent - the enum
+ * class is nested, not an inner class. The static block thus forces the
+ * class load of the outer class, which is needed to initialise the enums.
+ *
+ * @author Stephen Colebourne
+ * @version $Id: NestLinked.java,v 1.1 2003/11/29 15:03:54 scolebourne Exp $
+ */
+
+public final class NestLinked {
+
+ public static final ColorEnum RED = new ColorEnum("Red");
+ public static final ColorEnum GREEN = new ColorEnum("Green");
+ public static final ColorEnum BLUE = new ColorEnum("Blue");
+
+ public NestLinked() {
+ super();
+ }
+
+ public static final class ColorEnum extends Enum {
+
+ static {
+ // Explicitly reference the class where the enums are defined
+ Object obj = NestLinked.RED;
+ }
+
+ private ColorEnum(String color) {
+ super(color);
+ }
+
+ public static ColorEnum getEnum(String color) {
+ return (ColorEnum) getEnum(ColorEnum.class, color);
+ }
+
+ public static Map getEnumMap() {
+ return getEnumMap(ColorEnum.class);
+ }
+
+ public static List getEnumList() {
+ return getEnumList(ColorEnum.class);
+ }
+
+ public static Iterator iterator() {
+ return iterator(ColorEnum.class);
+ }
+ }
+}
diff --git a/src/test/org/apache/commons/lang/enum/NestReferenced.java b/src/test/org/apache/commons/lang/enum/NestReferenced.java
new file mode 100644
index 000000000..df59d06a2
--- /dev/null
+++ b/src/test/org/apache/commons/lang/enum/NestReferenced.java
@@ -0,0 +1,107 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowledgement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgement may appear in the software itself,
+ * if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ * Foundation" must not be used to endorse or promote products derived
+ * from this software without prior written permission. For written
+ * permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ *