1.ã¯ããã«
ãã®ãã¥ãŒããªã¢ã«ã§ã¯ãJava 7ã§å°å
¥ãããæ°ããããŒãžã§ã³ã§æ¡åŒµãããéèŠãªAPI java.lang.invoke.MethodHandlesã«ã€ããŠèª¬æããŸã ã
ã¡ãœãããã³ãã«ãšã¯äœããããããäœæããŠäœ¿çšããæ¹æ³ãåŠã³ãŸãã
2.ã¡ãœãããã³ãã«ãšã¯äœã§ããïŒ
APIããã¥ã¡ã³ãã§ã¯ãã¡ãœãããã³ãã«ã«ã¯æ¬¡ã®å®çŸ©ããããŸãã
ã¡ãœãããã³ãã«ã¯ãããŒã¹ã¡ãœãããã³ã³ã¹ãã©ã¯ã¿ãŒããã£ãŒã«ãããŸãã¯åŒæ°ãŸãã¯æ»ãå€ã®è¿œå ã®å€æã䌎ãä»ã®äœã¬ãã«æäœãžã®åä»ãã®å®è¡å¯èœãªåç
§ã§ãã
èšãæãããšãã¡ãœãããã³ãã«ã¯ãã¡ãœãããæ€çŽ¢ãé©åãããã³åŒã³åºãããã®äœã¬ãã«ã®ã¡ã«ããºã ã§ãã ã¡ãœãããã³ãã«ã¯äžå€ã§ããã衚瀺ç¶æ
ã¯ãããŸããã
MethodHandle
ãäœæããŠäœ¿çšããã«ã¯ã4ã€ã®ã¢ã¯ã·ã§ã³ãå®è¡ããå¿
èŠããããŸãã
- æ€çŽ¢èšè¿°åãäœæãã-ã«ãã¯ã¢ãã
- ã¡ãœããã¿ã€ãã®å®£èš
- æ€çŽ¢æ¹æ³ãã³ãã«
- ã¡ãœãããã³ãã«ãåŒã³åºã
2.1ã ã¡ãœãããã³ãã«ãšåå°
ã¡ãœãããã³ãã«ã¯ã java.lang.reflect APIãšãšãã«æ©èœããããã«å°å
¥ãããŸããã ãããã¯ç°ãªãç®çã®ããã«äœæãããç¹æ§ãç°ãªããŸãã
ããã©ãŒãã³ã¹ã®èŠ³ç¹ãããã¢ã¯ã»ã¹ãã§ãã¯ã¯å®è¡ã§ã¯ãªãäœææã«å®è¡ããããã ã MethodHandles APIã¯Reflection APIãããã¯ããã«é«éã§ã ã ã»ãã¥ãªãã£ãããŒãžã£ãŒãããå Žåããã®éãã¯å€§ãããªããŸãã ã¯ã©ã¹ã®æ€çŽ¢ãšãã®èŠçŽ ã®ååŸã«ã¯ãè¿œå ã®ãã§ãã¯ãå¿
èŠã§ãã
ãã ããããã©ãŒãã³ã¹ã¯ã¿ã¹ã¯ã®æé©æ§ã®å¯äžã®ææšã§ã¯ãããŸãããã¯ã©ã¹ã¡ãœããã®ååŸãã¢ã¯ã»ã¹ããŒã¯ã³ã®ãã§ãã¯ãªã©ã®ã¡ã«ããºã ããªããããMethodHandles APIã®äœ¿çšã¯ããå°é£ã§ããããšã«æ³šæããŠãã ããã
ããã«ãããããããMethodHandles APIã¯ã¡ãœããã®ã«ãªãŒåããã©ã¡ãŒã¿ãŒã®ã¿ã€ããšé åºã®å€æŽãèš±å¯ããŸãã
ããã§ãMethodHandles APIã®å®çŸ©ãšç®çãããã£ãã®ã§ãããããæäœã§ããŸãã ã¡ãœãããæ¢ãããšããå§ããŸãããã
3.ã«ãã¯ã¢ããã®äœæ
ã¡ãœãããã³ãã«ãäœæãããšãã«æåã«è¡ãããšã¯ãã«ãã¯ã¢ãããã¡ãœãããã³ã³ã¹ãã©ã¯ã¿ãããã³ã«ãã¯ã¢ããã¯ã©ã¹ã«è¡šç€ºããããã£ãŒã«ãã®ã¡ãœãããã³ãã«ãäœæãããã¡ã¯ããªãªããžã§ã¯ããååŸããããšã§ãã
MethodHandles APIã䜿çšãããšãããŸããŸãªã¢ã¯ã»ã¹ã¢ãŒãã§ã«ãã¯ã¢ãããªããžã§ã¯ããäœæã§ããŸãã
ãããªãã¯ã¡ãœãããžã®ã¢ã¯ã»ã¹ãæäŸããã«ãã¯ã¢ãããäœæããŸãã
MethodHandles.Lookup publicLookup = MethodHandles.publicLookup();
ãã ããprivateã¡ãœãããšprotectedã¡ãœããã«ã¢ã¯ã»ã¹ããå¿
èŠãããå Žåã¯ã代ããã«lookupïŒïŒã¡ãœããã䜿çšã§ããŸãã
MethodHandles.Lookup lookup = MethodHandles.lookup();
4. MethodTypeã®äœæ
MethodHandleãäœæããã«ã¯ãã«ãã¯ã¢ãããªããžã§ã¯ããåã«èšå®ããå¿
èŠããããããã¯MethodTypeã¯ã©ã¹ã䜿çšããŠå®è¡ã§ããŸãã
ç¹ã«ã MethodTypeã¯ãã¡ãœãããã³ãã«ã«ãã£ãŠåãå
¥ããããŠè¿ãããããŸãã¯åŒã³åºãã³ãŒãã«ãã£ãŠæž¡ãããŠäºæãããåŒæ°ãšæ»ãå€ã®åãè¡šããŸãã
MethodTypeæ§é ã¯åçŽã§ãæ»ãå€ã®åãšã察å¿ãããã©ã¡ãŒã¿ãŒåã®æ°ã«ãã£ãŠåœ¢æãããŸãããã©ã¡ãŒã¿ãŒåã¯ãã¡ãœãããã³ãã«ãšåŒã³åºãã³ãŒãã®éã§å®å
šã«å¯Ÿå¿ããå¿
èŠããããŸãã
MethodHandleãšåæ§ã«ãMethodTypeã®ãã¹ãŠã®ã€ã³ã¹ã¿ã³ã¹ã¯äžå€ã§ãã
java.util.List
ã¯ã©ã¹ãæ»ãå€ã®åãšããŠãObjecté
åãããŒã¿å
¥ååãšããŠå®çŸ©ããMethodTypeãå®çŸ©ããæ¹æ³ãèŠãŠã¿ãŸãããã
MethodType mt = MethodType.methodType(List.class, Object[].class);
ã¡ãœãããåçŽãŸãã¯voidåã®å€ãè¿ãå Žåããããã®åãè¡šãã¯ã©ã¹(void.class, int.class âŠ)
ãŸãã
intãè¿ããObjectãåãå
¥ããMethodTypeãå®çŸ©ããŸãã
MethodType mt = MethodType.methodType(int.class, Object.class);
MethodHandleã®äœæãéå§ã§ããŸãã
5. SearchMethodHandle
ã¡ãœããã®ã¿ã€ããèšå®ããåŸãMethodHandleãäœæããã«ã¯ãã«ãã¯ã¢ãããªããžã§ã¯ããŸãã¯publicLookupã䜿çšããŠæ€çŽ¢ããå¿
èŠããããŸããããã¯ããœãŒã¹ã¯ã©ã¹ãšã¡ãœããåãè¿ããŸãã
Lookupã¯ãã¡ãœããã®ã¹ã³ãŒããèæ
®ããŠãæé©ãªæ¹æ³ã§ã¡ãœãããã³ãã«ãèŠã€ããããšãã§ããäžé£ã®ã¡ãœãããæäŸããŸãã æãåçŽãªãã®ããå§ããŠãåºæ¬çãªã¢ãããŒããæ€èšããŠãã ããã
5.1ã ã¡ãœããã®ã¡ãœãããã³ãã«
findVirtual()
ã¡ãœããã䜿çšããŠãã€ã³ã¹ã¿ã³ã¹ã¡ãœããã®MethodHandleãäœæã§ããŸãã String
ã¯ã©ã¹ã®concat()
ã¡ãœããã«åºã¥ããŠäœæããŸãã
MethodType mt = MethodType.methodType(String.class, String.class); MethodHandle concatMH = publicLookup.findVirtual(String.class, "concat", mt);
5.2ã éçã¡ãœããã®ã¡ãœãããã³ãã«
éçã¡ãœããã«ã¢ã¯ã»ã¹ããã«ã¯ã findStatic()
ã¡ãœããã䜿çšã§ããŸãã
MethodType mt = MethodType.methodType(List.class, Object[].class); MethodHandle asListMH = publicLookup.findStatic(Arrays.class, "asList", mt);
ãã®å Žåã Object
åã®é
åãList
å€æããã¡ãœããã®ã¡ãœãããã³ãã«ãäœæããŸããã
5.3ã ã³ã³ã¹ãã©ã¯ã¿ãŒã®ã¡ãœãããã³ãã«
findConstructor()
ã¡ãœããã䜿çšããŠã³ã³ã¹ãã©ã¯ã¿ãŒã«ã¢ã¯ã»ã¹ã§ããŸãã
Stringãã©ã¡ãŒã¿ãŒãæã€Integerã¯ã©ã¹ã®ã³ã³ã¹ãã©ã¯ã¿ãŒãšåæ§ã®åäœãæã€ã¡ãœãããã³ãã«ãäœæããŸãã
MethodType mt = MethodType.methodType(void.class, String.class); MethodHandle newIntegerMH = publicLookup.findConstructor(Integer.class, mt);
5.4ã ãã£ãŒã«ãã®ã¡ãœãããã³ãã«
ã¡ãœãããã³ãã«ã䜿çšããŠããã£ãŒã«ãã«ã¢ã¯ã»ã¹ããããšãã§ããŸãã
Bookã¯ã©ã¹ãå®çŸ©ããããšããå§ããŸãããïŒ
public class Book { String id; String title;
åææ¡ä»¶ãšããŠãã¡ãœãããã³ãã«ãšå®£èšãããããããã£ã®éãçŽæ¥è¡šç€ºã§ãããããgetã¡ãœãããšåæ§ã®åäœãæã€ã¡ãœãããã³ãã«ãäœæã§ããŸãã
MethodHandle getTitleMH = lookup.findGetter(Book.class, "title", String.class);
å€æ°/ãã£ãŒã«ã管çã®è©³çŽ°ã«ã€ããŠã¯ã Java 9 Variable Handles Demystifiedã®èšäºãåç
§ããŠãã ãããJava9ã§å°å
¥ãããjava.lang.invoke.VarHandle APIã«ã€ããŠèª¬æããŠããŸã ã
5.5ã ãã©ã€ããŒãã¡ãœããã®ã¡ãœãããã³ãã«
java.lang.reflect APIã䜿çšããŠãprivateã¿ã€ãã®ã¡ãœããã®ã¡ãœãããã³ãã«ãäœæã§ããŸã ã
Bookã¯ã©ã¹ã®ãã©ã€ããŒãã¡ãœãããäœæããããšããå§ããŸãããã
private String formatBook() { return id + " > " + title; }
formatBook()
ã¡ãœããã®åäœã䜿çšããŠã¡ãœãããã³ãã«ãäœæã§ããŸãã
Method formatBookMethod = Book.class.getDeclaredMethod("formatBook"); formatBookMethod.setAccessible(true); MethodHandle formatBookMH = lookup.unreflect(formatBookMethod);
6.ã¡ãœãããã³ãã«ã®åŒã³åºã
ã¡ãœãããã³ãã«ãäœæãããã次ã®æé ã«é²ã¿ãŸãã MethodHandleã¯ã©ã¹ã¯ãã¡ãœãããã³ãã«ãåŒã³åºã3ã€ã®ç°ãªãæ¹æ³ãæäŸããŸãïŒ invoke()
ã invokeWithArugments()
ãããã³invokeExact()
ã
invoke
ã¡ãœããããå§ããŸãããã
6.1ã ã¡ãœãããã³ãã«ã®åŒã³åºã
invoke()
ã¡ãœããã䜿çšããå ŽåãåŒæ°ïŒã¢ãªãã£ïŒã®æ°ã¯åºå®ãããŸãããåŒæ°ãšæ»ãå€ã®åã®åãã£ã¹ããšããã¯/ã¢ã³ããã¯ãå®è¡ããããšã¯å¯èœã§ãã
次ã«ãããã¯ãããåŒæ°ã§invoke()
ã䜿çšããæ¹æ³invoke()
èŠãŠã¿ãŸãããã
MethodType mt = MethodType.methodType(String.class, char.class, char.class); MethodHandle replaceMH = publicLookup.findVirtual(String.class, "replace", mt); String output = (String) replaceMH.invoke("jovo", Character.valueOf('o'), 'a'); assertEquals("java", output);
ãã®å Žåã replaceMH
ã¯char
åŒæ°ãå¿
èŠãšããŸããã invoke()
ã¡ãœããã¯å®è¡åã«CharacteråŒæ°ãã¢ã³ããã¯ããŸãã
6.2ã åŒæ°ä»ãã§åŒã³åºã
invokeWithArguments
ã䜿çšããã¡ãœãããã³ãã«ã®invokeWithArguments
ã¯ãæå°éã®å¶éããããŸãã
å®éãåããã§ãã¯ããåŒæ°ãšæ»ãå€ãããã¯/ã¢ã³ããã¯ããããšã«å ããŠãå¯å€æ°ã®ãã©ã¡ãŒã¿ãŒã§åŒã³åºããè¡ãããšãã§ããŸãã
å®éã«ã¯ãé·ããäžæãªintå€ã®é
åã䜿çšããŠæŽæ°ãªã¹ããäœæã§ããŸãã
MethodType mt = MethodType.methodType(List.class, Object[].class); MethodHandle asList = publicLookup.findStatic(Arrays.class, "asList", mt); List<Integer> list = (List<Integer>) asList.invokeWithArguments(1, 2); assertThat(Arrays.asList(1,2), is(list));
6.3ã æ£ç¢ºãªåŒã³åºã
ã¡ãœãããã³ãã«ãïŒåŒæ°ã®ã»ãããšãã®åã«åŸã£ãŠïŒããå¶éçã«å®è¡ããå¿
èŠãããå Žåã¯ã invokeExact()
ã¡ãœããã䜿çšããŸãã
å®éãã¯ã©ã¹ã®åããã£ã¹ãããæ©èœã¯æäŸãããŠããããåŒæ°ã®åºå®ã»ãããå¿
èŠã§ãã
ã¡ãœãããã³ãã«ã䜿çšããŠ2ã€ã®intå€ãè¿œå ããæ¹æ³ãèŠãŠã¿ãŸãããã
MethodType mt = MethodType.methodType(int.class, int.class, int.class); MethodHandle sumMH = lookup.findStatic(Integer.class, "sum", mt); int sum = (int) sumMH.invokeExact(1, 11); assertEquals(12, sum);
ãã®å Žåã invokeExact
ã¡ãœããã«intã§ã¯ãªãæ°å€ãæž¡ããšãåŒã³åºããšãã«WrongMethodTypeException
ãŸãã
7.é
åãæäœãã
MethodHandlesã¯ããã£ãŒã«ããšãªããžã§ã¯ãã ãã§ãªããé
åã§ãæ©èœããŸãã asSpreader()
APIã䜿çšããŠãäœçœ®åŒæ°ãšããŠé
åããµããŒãããã¡ãœãããã³ãã«ãäœæã§ããŸãã
ãã®å Žåãã¡ãœãããã³ãã«ã¯é
åãåãåãããã®èŠçŽ ãäœçœ®åŒæ°ãšããŠããªãã·ã§ã³ã§é
åã®é·ããšããŠé
åžããŸãã
é
åã®åŒæ°ãåãæååã§ãããã©ããããã§ãã¯ããã¡ãœãããã³ãã«ãååŸããæ¹æ³ãèŠãŠã¿ãŸãããã
MethodType mt = MethodType.methodType(boolean.class, Object.class); MethodHandle equals = publicLookup.findVirtual(String.class, "equals", mt); MethodHandle methodHandle = equals.asSpreader(Object[].class, 2); assertTrue((boolean) methodHandle.invoke(new Object[] { "java", "java" }));
8.ã¡ãœãããã³ãã«ã®æ確å
ã¡ãœãããã³ãã«ãèšå®ããããšãã¡ãœãããåŒã³åºããã«åŒæ°ã«ãã€ã³ãããããšã§ãããã調æŽã§ããŸãã
ããšãã°ãJava 9ã§ã¯ããã®ããªãã¯ã䜿çšããŠæååã®é£çµãæé©åããŸãã
æ¥å°ŸèŸãconcatMH
ä»å ããããšã§ãé£çµãã©ã®ããã«è¡ãããããèŠãŠã¿ãŸãããã
MethodType mt = MethodType.methodType(String.class, String.class); MethodHandle concatMH = publicLookup.findVirtual(String.class, "concat", mt); MethodHandle bindedConcatMH = concatMH.bindTo("Hello "); assertEquals("Hello World!", bindedConcatMH.invoke("World!"));
9. Java 9ã¢ããããŒã
Java 9ã§ã¯ãMethodHandles APIã«ããã€ãã®å€æŽãå°å
¥ããã䜿ãããããªããŸããã
æŽæ°ã¯3ã€ã®äž»ãªåŽé¢ã«é¢ä¿ããŸãã
- ã«ãã¯ã¢ããæ©èœ -ããŸããŸãªã³ã³ããã¹ãããã®æ€çŽ¢ãå¯èœã«ããã€ã³ã¿ãŒãã§ãŒã¹ã§éæœè±¡ã¡ãœããããµããŒãããŸãã
- åŒæ°ã®ããæäœ - åŒæ°ã®æãããã¿ãåéãé
åžã®æ©èœãæ¹åããŸãã
- è¿œå ã®çµã¿åããã¯ãã«ãŒãæäœïŒ
loop
ã whileLoop
ã doWhileLoop
ãªã©ïŒã®è¿œå ãštryFinally
äŸå€ç®¡çã®æ¹åtryFinally
ã
ãããã®å€æŽã«ã¯ãä»ã®æçšãªé©æ°ã䌎ããŸããã
- JVMã³ã³ãã€ã©æé©åã®æ¹å
- æžå°ããã€ã³ã¹ã¿ã³ã¹
- MethodHandles APIã®äœ¿çšã®å
·äœå
å€æŽã®ãã詳现ãªãªã¹ãã¯ãJavadoc MethodHandles APIã§å
¥æã§ããŸã ã
10.çµè«
ãã®èšäºã§ã¯ãMethodHandles APIã«åºäŒããã¡ãœãããã³ãã«ãšã¯äœãããããŠãããã䜿çšããæ¹æ³ã«ã€ããŠãåŠã³ãŸããã
ãŸããReflection APIãšã®é¢é£ä»ãã«ã€ããŠã説æããŸããã ã¡ãœãããã³ãã«ã®åŒã³åºãã¯ããªãäœã¬ãã«ã®æäœã§ããããããããã®äœ¿çšã¯ã¿ã¹ã¯ã«æ£ç¢ºã«é©åããå Žåã«ã®ã¿æ£åœåãããŸãã
ãã€ãã®ããã«ãèšäºã®ãã¹ãŠã®ãœãŒã¹ã³ãŒãã¯Githubã§å
¥æã§ããŸã ã