2016-03-18 7 views
5

को int[]::new जैसे सरणी कन्स्ट्रक्टर के लिए मैं कैसे प्राप्त करूं?मैं MethodHandles.Lookup के साथ एक सरणी कन्स्ट्रक्टर MethodHandle को कैसे देखूं?

यह काम नहीं करता:

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 
[email protected] 

उत्तर

4

जैसा कि मुझे पता है int[].class में कोई कन्स्ट्रक्टर नहीं है, इसलिए यह कम से कम प्रतिबिंब के माध्यम से उपलब्ध नहीं है।

इसके बजाय, आप सरणी के कारखाने पद्धति पर MethodHandle प्राप्त करने की कोशिश कर सकते हैं:

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

और यह फोन करके एक सरणी पैदा करते हैं।

+2

बस 'पूर्णांक [] कि जाँच :: नई 'ऑब्जेक्ट लैम्ब्डा $ एमआर $ नया $ नया $ 4ffde7b3 $ 1 (int len) {by new int [len] जैसे बाइटकोड सिंथेटिक विधि में उत्पन्न करता है; } '। –

+0

प्रश्न के संदर्भ में, आप निश्चित रूप से '.bindTo (int.class) .asType (MethodType.methodType (int []। Class, int.class) को चेन करना चाहते हैं)' वांछित हैंडल को 'int' का प्रतिनिधित्व करने के लिए [] :: नया 'तर्क, यानी आप इसे' int [] array = (int []) mh.invokeExact (42) की तरह उपयोग कर सकते हैं; ' – Holger

+0

सभी के लिए धन्यवाद। यह मेरे लिए काम करता है: 'MethodHandles.insertArguments (lookup.findStatic (Array.class, "newInstance", MethodType.methodType (Object.class, class.class, int.class)), 0, int.class) ' – Archie

1

लगता है कि @MaximSIvanov सही है: इस तरह के विधि संभाल पाने के लिए कोई अंतर्निहित तरीका नहीं है। हालांकि कुछ भी नहीं इस विधि को इस उद्देश्य के लिए एक विशेष विधि एक हैंडल बनाने और प्रदान से आप बंद हो जाता है: जब आप int[]::new विधि संदर्भ संकलन

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

कुछ इसी तरह की वास्तव में जावा संकलक द्वारा किया जाता है: सहायक निजी विधि बनाई गई है। आप निम्न वर्ग संकलन के द्वारा जाँच कर सकते हैं:

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 
संबंधित मुद्दे