我需要调用字段访问器方法,即泛型枚举的getter,但无法弄清楚如何调用方法,或者更具体地说,如何将泛型枚举作为invoke-method的参数传递。
在此先感谢,感谢任何帮助。
这是我想或多或少做的事。
public void(Class<? extends Enum<?>> enumType) {
Enum<?>[] enumConstants = enumType.getEnumConstants();
String[] text = new String[enumConstants.length];
String[] names = new String[enumConstants.length];
for (int i = 0; i < enumConstants.length; i++ ) {
Method[] methods = enumConstants[i].getClass().getDeclaredMethods();
for (Method m: enumConstants[i].getClass().getDeclaredMethods()) {
System.out.println(enumConstants[i].name() + ": " + m.getName() + "()");
try {
if (GET_KEY_METHOD_NAME.equalsIgnoreCase(m.getName())) {
Object value = m.invoke(I HAVE NO IDEA WHAT TO PUT HERE, "");
System.out.println(value.toString());
}
if (GET_VALUE_METHOD_NAME.equalsIgnoreCase(m.getName())) {
Object value = m.invoke(I HAVE NO IDEA WHAT TO PUT HERE, "");
System.out.println(value.toString());
}
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
答案 0 :(得分:2)
Method.invoke
方法的参数始终是调用方法的实例,后跟参数列表。
Object value = m.invoke(enumConstants[i]);
很可能是你需要的。
另外,您应该在方法中添加一个类型参数:
public <T extends Enum<T>> void myMethod(Class<T> enumType) {
T[] enumConstants = enumType.getEnumConstants();
BTW:您是否考虑过使用包含这些方法的interface
?这将允许您访问方法而无需使用反射。
另请参阅getDeclaredMethod
方法,并记住枚举常量可以是枚举类的子类的实例,因此您应该使用不包含Declared
的方法。还可以找到枚举类的方法,而不是查找较少查找的单个类:
例如,请考虑以下事项:
public enum MyEnum implements M1M2Interface {
ONE() {
@Override
public String m1(String s) {
return "1";
}
}, TWO() {
@Override
public int m2(BigInteger i) {
return 2;
}
}
;
}
public interface M1M2Interface {
default String m1(String s) {
return "2";
}
default int m2(BigInteger i) {
return 1;
}
}
public static <T extends Enum<T>> void testEnum(Class<T> enumType) throws NoSuchMethodException {
T[] enumConstants = enumType.getEnumConstants();
Method m1 = enumType.getMethod("m1", String.class);
Method m2 = enumType.getMethod("m2", BigInteger.class);
for (int i = 0; i < enumConstants.length; i++) {
System.out.println(enumConstants[i].name() + ":");
try {
System.out.println(" m1:" + m1.invoke(enumConstants[i], "Hello World"));
System.out.println(" m2:" + m2.invoke(enumConstants[i], (BigInteger) null));
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
ex.printStackTrace();
}
}
}
getDeclaredMethod
在这里不起作用,因为这些方法可以通过以下方式声明/实现:
EnumName.CONSTANT_NAME.methodName()
访问该方法,因此不太可能完成...)答案 1 :(得分:1)
反思很少是对任何事情的正确答案。考虑让您的枚举类实现一个通用接口,例如StandardCopyOption和Month。
如果你不能修改枚举类,并且你正在使用Java 8,你可以将getter方法作为参数传递:
public <E extends Enum<E>> E findMatch(Class<E> enumClass,
Function<E, String> nameGetter,
Predicate<String> matcher) {
for (E value : EnumSet.allOf(enumClass)) {
String name = nameGetter.apply(value);
if (matcher.test(name)) {
return value;
}
}
return null;
}
使用示例:
public static enum Season {
SPRING("Spr"),
SUMMER("Sum"),
FALL("Fal"),
WINTER("Win");
private final String abbreviation;
private Season(String abbrev) {
this.abbreviation = abbrev;
}
public getAbbreviation() {
return abbreviation;
}
}
public void doStuff() {
// ...
String abbrToFind = "Sum";
Season match = findMatch(Season.class,
Season::getAbbreviation,
Predicate.isEqual(abbrToFind));
}
如果您使用的是早于Java 8的版本,您仍然可以执行相同的操作,但您需要自己定义和实现这些接口:
public interface Function<A, B> {
B apply(A input);
}
public interface Predicate<T> {
boolean test(T value);
}
public void doStuff() {
// ...
final String abbrToFind = "Sum";
Season match = findMatch(Season.class,
new Function<Season, String>() {
@Override
public String apply(Season season) {
return season.getAbbreviation(),
}
},
new Predicate<String>() {
@Override
public boolean test(String name) {
return Objects.equals(name, abbrToFind);
}
});
}