I have an enum with anonymous inner class like:
public enum Status {
PRELIMINARY() {
@Override
boolean process() {
return true;
}
SUBMITTED() {
@Override
boolean process() {
return false;
}
abstract boolean process();
}
I have a model like
public class Foo {
private Status status;
public void setStatus(Status status) {
this.status = status;
}
}
I need to use reflection to set a Foo.status
like:
private static <T> void setFieldValue(Foo instance, Class<?> klazz, Object value) {
try {
Class<?> aClass = value.getClass(); // Is Status$1 instead of Status
Method method = klazz.getDeclaredMethod(getSetterName('setStatus'), aClass);
method.invoke(instance, value);
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
if (!klazz.equals(Object.class)) {
setFieldValue(instance, klazz.getSuperclass(), fieldName, value);
}
}
}
This works when Status
does not contain an inner class and is a simple enum, however for the above Status
class it will throw a NoSuchMethodException
. This is because the class of my value will be package.Status$1
instead of package.Status
.
Is there a good work around for this?
You just need to change your means of locating the desired method. Something like the following should work:
private static @Nullable Method findMethod(Class<?> klass,
final String methodName,
final Object... args) {
@Nullable Method candidate = null;
classSearch:
while (klass != null) {
// Check all the class' methods for a matching one.
methodSearch:
for (final Method method : klass.getDeclaredMethods()) {
if (!method.getName().equals(methodName)) continue;
final Class<?>[] parameterTypes = method.getParameterTypes();
if (parameterTypes.length != args.length) continue;
// Check all parameters can come from the given args.
for (int i = 0; i < args.length; i++) {
if (!parameterTypes[i].isInstance(args[i])) continue methodSearch;
}
candidate = method;
break classSearch;
}
// No matching method, check super class.
klass = klass.getSuperclass();
}
// May be 'null' if no match was found.
// Throw an Exception if this isn't a valid outcome in your case.
return candidate;
}
Chaining this with your existing code (calling .invoke
on the returned Method
(if it's not null
)) should give you the desired outcome.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.