如何检索构造函数·实例初始化器·静态初始化器作为方法?

时间:2015-03-03 16:41:02

标签: java reflection methods

据我所知,构造函数,实例初始化器和静态初始化器只是具有特殊名称的方法。我知道<>是普通标识符的非法字符。

如何将这些特殊方法检索为Method个对象(或类似的东西)并调用他们?你可以看看我写的这段代码片段:

public class Program {
    /**
     * static <init>() {
     * }
     */
    static {
    }

    /**
     * <init>() {
     * }
     */
    {
    }

    /**
     * <cinit>() {
     * }
     */
    Program(){
    }

    public static void main(String[] args) throws ReflectiveOperationException {
        //get native getDeclaredMethods method
        Method Class$getDeclaredMethods0 = Class.class.getDeclaredMethod("getDeclaredMethods0", boolean.class);
        Class$getDeclaredMethods0.setAccessible(true);

        //list methods of this class
        Method[] methods = (Method[])Class$getDeclaredMethods0.invoke(Program.class, false);
        for (Method m : methods) {
            System.out.println(m);
        }

        //Console output:
        /*
        public static void dirty.Program.main(java.lang.String[]) throws java.lang.ReflectiveOperationException

         */
    }
}

2 个答案:

答案 0 :(得分:0)

你做不到。您可以为声明的构造函数获取Constructor个实例,但是没有Java类型表示可调用的静态或实例初始化程序。

答案 1 :(得分:0)

你不能使用静态初始化程序。对于实例初始化程序,它们由构造函数执行,如果没有关联的构造函数执行它们就没有意义(它们要求实例存在)。

从Java 7和java.lang.invoke开始,您可以将MethodHandle用于构造函数。您将以与常规方法相同的方式调用它们。例如,这是我用于构建异常实例的代码的提取(注意:Java 8):

private static final Lookup LOOKUP
    = MethodHandles.publicLookup();

// Method type for a constructor accepting a Throwable as an argument
private static final MethodType TYPE
    = MethodType.methodType(void.class, Throwable.class);

private MethodHandle getHandle(final Class<? extends RuntimeException> c)
{
    return handles.computeIfAbsent(c, key -> {
        try {
            return LOOKUP.findConstructor(c, TYPE)
                .asType(TYPE.changeReturnType(RuntimeException.class));
        } catch (IllegalAccessException | NoSuchMethodException e) {
            throw new InstantiationException(e);
        }
    });
}

@SuppressWarnings("unchecked")
public <E extends RuntimeException> E get(final Class<E> c,
    final Throwable t)
{
    try {
        return (E) getHandle(c).invokeExact(t);
    } catch (InstantiationException e) {
        e.addSuppressed(t);
        throw e;
    } catch (Error | RuntimeException e) {
        throw e;
    } catch (Throwable oops) {
        final RuntimeException exception = new InstantiationException(oops);
        exception.addSuppressed(t);
        throw exception;
    }
}