简体   繁体   English

如何使用MethodHandles.Lookup查找数组构造函数MethodHandle?

[英]How do I lookup an array constructor MethodHandle with MethodHandles.Lookup?

How do I get the MethodHandle for an array constructor like int[]::new ? 如何获取像int[]::new这样的数组构造函数的MethodHandle

This doesn't work: 这不起作用:

public static void main(String[] args) throws Throwable {
    MethodHandles.Lookup lookup = MethodHandles.publicLookup();
    MethodHandle mh = lookup.findConstructor(int[].class, MethodType.methodType(void.class, int.class));
    System.out.println(mh);
    System.out.println(mh.invoke());
}

It results in this: 结果如下:

Exception in thread "main" java.lang.NoSuchMethodException: no such constructor: [I.<init>(int)void/newInvokeSpecial
    at java.lang.invoke.MemberName.makeAccessException(MemberName.java:871)
    at java.lang.invoke.MemberName$Factory.resolveOrFail(MemberName.java:990)
    at java.lang.invoke.MethodHandles$Lookup.resolveOrFail(MethodHandles.java:1382)
    at java.lang.invoke.MethodHandles$Lookup.findConstructor(MethodHandles.java:920)
    at xx.main(xx.java:11)
Caused by: java.lang.NoSuchMethodError: java.lang.Object.<init>(I)V
    at java.lang.invoke.MethodHandleNatives.resolve(Native Method)
    at java.lang.invoke.MemberName$Factory.resolve(MemberName.java:962)
    at java.lang.invoke.MemberName$Factory.resolveOrFail(MemberName.java:987)
    ... 3 more

Nor does this: 这也不是:

public static void main(String[] args) throws Throwable {
    MethodHandles.Lookup lookup = MethodHandles.publicLookup();
    MethodHandle mh = lookup.findConstructor(int[].class, MethodType.methodType(void.class));
    System.out.println(mh);
    System.out.println(mh.invoke());
}

It seems to find the constructor for Object instead: 它似乎找到了Object的构造函数:

MethodHandle()Object
java.lang.Object@36baf30c

As I know int[].class has no constructor, so it's not available via reflection at least. 我知道int[].class没有构造函数,所以它至少不能通过反射来获得。

Instead, you can try to get MethodHandle on Array's factory method: 相反,您可以尝试在Array的工厂方法上获取MethodHandle

MethodHandle mh = lookup.findStatic(Array.class, "newInstance",
                             MethodType.methodType(Object.class, Class.class, int.class));

and create an array by calling it. 并通过调用它来创建一个数组。

Seems that @MaximSIvanov is right: there's no built-in way to get such method handle. 似乎@MaximSIvanov是对的:没有内置的方法来获得这样的方法处理。 However nothing stops you from creating a special method for this purpose and provide a handle to this method: 但是,没有什么能阻止您为此目的创建特殊方法并提供此方法的句柄:

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.util.Arrays;

public class ArrayMethodHandles {
    private static int[] makeIntArray(int size) {
        return new int[size];
    }

    public static MethodHandle createIntArray() {
        try {
            return MethodHandles.lookup().findStatic(ArrayMethodHandles.class, 
                "makeIntArray", MethodType.methodType(int[].class, int.class));
        } catch (NoSuchMethodException | IllegalAccessException e) {
            throw new InternalError();
        }
    }

    public static void main(String[] args) throws Throwable {
        MethodHandle mh = createIntArray();
        int[] array = (int[])mh.invokeExact(10);
        System.out.println(Arrays.toString(array));
        // prints [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
    }
}

Something similar is actually performed by java compiler when you compile int[]::new method reference: helper private method is created. 编译int[]::new方法引用时,java编译器实际上执行了类似的操作:创建了helper私有方法。 You may check by compiling the following class: 您可以通过编译以下类来检查:

import java.util.function.*;

public class Test { 
    IntFunction<int[]> fn = int[]::new;
}

Running javap -p -c Test you will see that helper private method is generated and linked as MethodHandle to invokedynamic : 运行javap -p -c Test您将看到生成辅助私有方法并将其作为MethodHandle链接到invokedynamic

private static java.lang.Object lambda$MR$new$new$4ffde7b3$1(int);
    Code:
       0: iload_0
       1: newarray       int
       3: areturn

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM