net.dongliu.commons.reflect.InstanceMethod Maven / Gradle / Ivy
package net.dongliu.commons.reflect;
import net.dongliu.commons.Exceptions;
import net.dongliu.commons.exception.ReflectException;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Objects;
/**
* @author Liu Dong
*/
public class InstanceMethod {
private final Method method;
private final MethodHandle methodHandle;
public InstanceMethod(Method method) {
Objects.requireNonNull(method);
if (Modifier.isStatic(method.getModifiers())) {
throw new IllegalArgumentException("Method should not be static");
}
this.method = method;
this.methodHandle = getHandle(method);
}
private MethodHandle getHandle(Method method) {
method.setAccessible(true);
MethodHandles.Lookup lookup = MethodHandles.lookup();
try {
// private function can invoke special instead of invoke virtual, however we can not use unreflectSpecial
// when do not have private access to the class
return lookup.unreflect(method);
} catch (IllegalAccessException e) {
throw new ReflectException(e);
}
}
/**
* Return method name
*/
public String name() {
return method.getName();
}
/**
* Get method handle
*/
public MethodHandle methodHandle() {
return methodHandle;
}
/**
* Invoke method with return values
*/
public Object call(Object instance, Object... args) {
if (method.getReturnType() == void.class) {
// no return value
run(instance, args);
return null;
}
args = concat(Objects.requireNonNull(instance), args);
try {
return methodHandle.invokeWithArguments(args);
} catch (Throwable throwable) {
throw Exceptions.sneakyThrow(throwable);
}
}
/**
* Invoke method with no value
*/
public void run(Object instance, Object... args) {
args = concat(Objects.requireNonNull(instance), args);
try {
methodHandle.invokeWithArguments(args);
} catch (Throwable throwable) {
throw Exceptions.sneakyThrow(throwable);
}
}
private Object[] concat(Object instance, Object[] args) {
if (args.length == 0) {
return new Object[]{instance};
}
Object[] objects = new Object[args.length + 1];
objects[0] = instance;
System.arraycopy(args, 0, objects, 1, args.length);
return objects;
}
/**
* Invoke method with return values
*/
public Object call(Object instance) {
if (method.getReturnType() == void.class) {
// no return value
run(instance);
return null;
}
try {
return methodHandle.invoke(instance);
} catch (Throwable throwable) {
throw Exceptions.sneakyThrow(throwable);
}
}
/**
* Invoke method with no value
*/
public void run(Object instance) {
try {
methodHandle.invoke(instance);
} catch (Throwable throwable) {
throw Exceptions.sneakyThrow(throwable);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy