6

MethodHandleのような配列コンストラクターを取得するにはどうすればよいint[]::newですか?

これは機能しません:

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());
}

その結果、次のようになります。

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

これもありません:

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());
}

Object代わりにコンストラクターを見つけるようです:

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

2 に答える 2

1

@MaximSIvanovが正しいようです。そのようなメソッドハンドルを取得する組み込みの方法はありません。ただし、この目的のために特別なメソッドを作成し、このメソッドへのハンドルを提供することを止めるものは何もありません。

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]
    }
}

int[]::newメソッド参照をコンパイルすると、似たようなことが実際に Java コンパイラによって実行されます。ヘルパー プライベート メソッドが作成されます。次のクラスをコンパイルして確認できます。

import java.util.function.*;

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

実行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
于 2016-03-18T04:54:29.980 に答える