リフレクションによってEnum値を取得するプログラム(Enumは許可されています)があり、その型パラメータとしてEnumをとる汎用クラスでラップすることで何かしたい。しかし、コンストラクタを正しく呼び出す方法がわかりません。私はそれが動作するようにすることができる唯一の方法は、生のタイプを使用することです。リフレクションで得られた列挙定数を使用しています
(説明:実際のプログラムは複雑で、実行時にユーザー提供のファイルからenumクラス名を参照します。実際のプログラムのラッパークラスには、enumで実現できない追加の状態とメソッドがあります。ただ学術ためにこれをやっていないメートル。私はそれが不自然に見えることがあります。この問題を説明するために以下の例のプログラムを書いたが、例示的な目的のためにすることになっています。)
誰も私がライン
を修正するのに役立つことができますEnumWrapper<?> ewrapped = new EnumWrapper(e);
以下のように警告が少なくなりますか?
プログラムは期待どおりに動作します(見つからない列挙型の例外は3つありますが、それ以外の場合はラップされた列挙型のリストを出力します)。しかし、生の型を決して使用しないで、この場合を修正する。
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<E extends Enum<E>>
{
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 <E extends Enum<E>> EnumWrapper<E> wrap(E e) {
return new EnumWrapper<E>(e);
}
}
public static void main(String[] args) {
List<EnumWrapper<?>> list = new ArrayList<EnumWrapper<?>>();
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<?> e = getEnum(className);
// EnumWrapper<?> ewrapped0 = EnumWrapper.wrap(e);
/*
* Bound mismatch: The generic method wrap(E) of type
* GenericEnum2.EnumWrapper<E> is not applicable for
* the arguments (Enum<capture#2-of ?>). The inferred
* type Enum<capture#2-of ?> is not a valid substitute for
* the bounded parameter <E extends Enum<E>>
*/
// EnumWrapper<?> ewrapped0 = new EnumWrapper<?>(e);
// Cannot instantiate the type GenericEnum2.EnumWrapper<?>
EnumWrapper<?> 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<?> 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<Enum> cl = (Class<Enum>)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;
}
}
編集:更新getEnum()OrangeDogの提案あたり:
static public Enum<?> getEnum(String enumFullName) throws IllegalArgumentException, ClassNotFoundException
{
String[] x = enumFullName.split("\\.(?=[^\\.]+$)");
if (x.length == 2)
{
String enumClassName = x[0];
String enumName = x[1];
final Class<?> cl = Class.forName(enumClassName);
if (cl.isEnum())
{
for (Object o : cl.getEnumConstants())
{
Enum<?> e = (Enum<?>)o;
if (enumName.equals(e.name()))
return e;
}
}
else
throw new IllegalArgumentException("Class is not an enum: "+enumClassName);
}
return null;
}
}
この例はかなり複雑です。コードをもっと簡単にしてラッパーを削除することをお勧めします。 –
合意しましたが、静的なファクトリメソッドを除いては便利なメソッドはありません。 – maaartinus
これは 'Arrays.asList(Bird.OWL、Bird.EAGLE、Bird.HAWK、Mammal.LION、Mammal.TIGER、Mammal.BEAR)' –