Note that there are some explanatory texts on larger screens.

plurals
  1. POusing enum constants obtained through reflection
    primarykey
    data
    text
    <p>I have a program which obtains an Enum value via reflection (any Enum is allowed), and I want to do something with it by wrapping it in a generic class that takes an Enum as its type parameter. I am not sure how to properly call the constructor, however. The only way I can get it to work is to use a raw type.</p> <p>(<strong>clarification:</strong> My real program is complicated, and looks up the enum classname from a user-provided file at runtime. My real program's wrapper class has additional state and methods that cannot be accomplished with an enum, so I'm not just doing this for academic sake. I wrote the example program below to illustrate the issue. It may look contrived, but it's supposed to be for illustrative purposes.)</p> <p>Can anyone help me fix the line</p> <pre><code>EnumWrapper&lt;?&gt; ewrapped = new EnumWrapper(e); </code></pre> <p>below so it has a less evil warning? </p> <p>The program works as expected (prints out stack traces of 3 caught exceptions for enum constants not found, otherwise prints lists of wrapped enums), but I make it a habit never to use raw types, and don't know how to fix this case.</p> <pre><code>import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class GenericEnum2 { enum Bird { OWL, EAGLE, HAWK }; enum Mammal { LION, TIGER, BEAR }; static class EnumWrapper&lt;E extends Enum&lt;E&gt;&gt; { final private E value; public EnumWrapper(E value) { this.value = value; } public E getEnum() { return this.value; } @Override public String toString() { return "wrapped "+value.toString(); } static public &lt;E extends Enum&lt;E&gt;&gt; EnumWrapper&lt;E&gt; wrap(E e) { return new EnumWrapper&lt;E&gt;(e); } } public static void main(String[] args) { List&lt;EnumWrapper&lt;?&gt;&gt; list = new ArrayList&lt;EnumWrapper&lt;?&gt;&gt;(); list.add(EnumWrapper.wrap(Bird.OWL)); list.add(EnumWrapper.wrap(Bird.EAGLE)); list.add(EnumWrapper.wrap(Bird.HAWK)); list.add(EnumWrapper.wrap(Mammal.LION)); list.add(EnumWrapper.wrap(Mammal.TIGER)); list.add(EnumWrapper.wrap(Mammal.BEAR)); System.out.println(list); list.clear(); for (String s : Arrays.asList( "Bird.OWL", "Bird.HAWK", "Bird.FULVOUS_WHISTLING_DUCK", "Mammal.LION", "Mammal.BEAR", "Mammal.WARTHOG", "Computer.COMMODORE_64" )) { String className = GenericEnum2.class.getCanonicalName()+"$"+s; try { Enum&lt;?&gt; e = getEnum(className); // EnumWrapper&lt;?&gt; ewrapped0 = EnumWrapper.wrap(e); /* * Bound mismatch: The generic method wrap(E) of type * GenericEnum2.EnumWrapper&lt;E&gt; is not applicable for * the arguments (Enum&lt;capture#2-of ?&gt;). The inferred * type Enum&lt;capture#2-of ?&gt; is not a valid substitute for * the bounded parameter &lt;E extends Enum&lt;E&gt;&gt; */ // EnumWrapper&lt;?&gt; ewrapped0 = new EnumWrapper&lt;?&gt;(e); // Cannot instantiate the type GenericEnum2.EnumWrapper&lt;?&gt; EnumWrapper&lt;?&gt; ewrapped = new EnumWrapper(e); // this works but gives me the warning of "EnumWrapper" being a raw type list.add(ewrapped); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } System.out.println(list); } static public Enum&lt;?&gt; getEnum(String enumFullName) throws IllegalArgumentException, ClassNotFoundException { String[] x = enumFullName.split("\\.(?=[^\\.]+$)"); if (x.length == 2) { String enumClassName = x[0]; String enumName = x[1]; @SuppressWarnings("unchecked") final Class&lt;Enum&gt; cl = (Class&lt;Enum&gt;)Class.forName(enumClassName); if (cl.isEnum()) { @SuppressWarnings("unchecked") final Enum result = Enum.valueOf(cl, enumName); return result; } else throw new IllegalArgumentException("Class is not an enum: "+enumClassName); } return null; } } </code></pre> <hr> <p>edit: updated getEnum() per OrangeDog's suggestions:</p> <pre><code>static public Enum&lt;?&gt; getEnum(String enumFullName) throws IllegalArgumentException, ClassNotFoundException { String[] x = enumFullName.split("\\.(?=[^\\.]+$)"); if (x.length == 2) { String enumClassName = x[0]; String enumName = x[1]; final Class&lt;?&gt; cl = Class.forName(enumClassName); if (cl.isEnum()) { for (Object o : cl.getEnumConstants()) { Enum&lt;?&gt; e = (Enum&lt;?&gt;)o; if (enumName.equals(e.name())) return e; } } else throw new IllegalArgumentException("Class is not an enum: "+enumClassName); } return null; } } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload