All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.dongliu.commons.reflect.InstanceMethod Maven / Gradle / Ivy

There is a newer version: 12.0.2
Show newest version
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