BAEL-1441: Method Handles in Java 9 (#3565)
* Added MethodHandles API code * Added Reflection API example for comparison
This commit is contained in:
parent
ea306bec5f
commit
9801a08599
|
@ -0,0 +1,17 @@
|
|||
package com.baeldung.java9.methodhandles;
|
||||
|
||||
public class Book {
|
||||
|
||||
String id;
|
||||
String title;
|
||||
|
||||
public Book(String id, String title) {
|
||||
this.id = id;
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private String formatBook() {
|
||||
return id + " > " + title;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,152 @@
|
|||
package com.baeldung.java9.methodhandles;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.lang.invoke.WrongMethodTypeException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Test case for the {@link MethodHandles} API
|
||||
*/
|
||||
public class MethodHandlesTest {
|
||||
|
||||
@Test
|
||||
public void givenConcatMethodHandle_whenInvoked_thenCorrectlyConcatenated() throws Throwable {
|
||||
|
||||
MethodHandles.Lookup publicLookup = MethodHandles.publicLookup();
|
||||
MethodType mt = MethodType.methodType(String.class, String.class);
|
||||
MethodHandle concatMH = publicLookup.findVirtual(String.class, "concat", mt);
|
||||
|
||||
String output = (String) concatMH.invoke("Effective ", "Java");
|
||||
|
||||
assertEquals("Effective Java", output);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenAsListMethodHandle_whenInvokingWithArguments_thenCorrectlyInvoked() throws Throwable {
|
||||
MethodHandles.Lookup publicLookup = MethodHandles.publicLookup();
|
||||
MethodType mt = MethodType.methodType(List.class, Object[].class);
|
||||
MethodHandle asListMH = publicLookup.findStatic(Arrays.class, "asList", mt);
|
||||
|
||||
List<Integer> list = (List<Integer>) asListMH.invokeWithArguments(1, 2);
|
||||
|
||||
assertThat(Arrays.asList(1, 2), is(list));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenConstructorMethodHandle_whenInvoked_thenObjectCreatedCorrectly() throws Throwable {
|
||||
MethodHandles.Lookup publicLookup = MethodHandles.publicLookup();
|
||||
MethodType mt = MethodType.methodType(void.class, String.class);
|
||||
MethodHandle newIntegerMH = publicLookup.findConstructor(Integer.class, mt);
|
||||
|
||||
Integer integer = (Integer) newIntegerMH.invoke("1");
|
||||
|
||||
assertEquals(1, integer.intValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenAFieldWithoutGetter_whenCreatingAGetter_thenCorrectlyInvoked() throws Throwable {
|
||||
MethodHandles.Lookup lookup = MethodHandles.lookup();
|
||||
MethodHandle getTitleMH = lookup.findGetter(Book.class, "title", String.class);
|
||||
|
||||
Book book = new Book("ISBN-1234", "Effective Java");
|
||||
|
||||
assertEquals("Effective Java", getTitleMH.invoke(book));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenPrivateMethod_whenCreatingItsMethodHandle_thenCorrectlyInvoked() throws Throwable {
|
||||
MethodHandles.Lookup lookup = MethodHandles.lookup();
|
||||
Method formatBookMethod = Book.class.getDeclaredMethod("formatBook");
|
||||
formatBookMethod.setAccessible(true);
|
||||
|
||||
MethodHandle formatBookMH = lookup.unreflect(formatBookMethod);
|
||||
|
||||
Book book = new Book("ISBN-123", "Java in Action");
|
||||
|
||||
assertEquals("ISBN-123 > Java in Action", formatBookMH.invoke(book));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenReplaceMethod_whenUsingReflectionAndInvoked_thenCorrectlyReplaced() throws Throwable {
|
||||
Method replaceMethod = String.class.getMethod("replace", char.class, char.class);
|
||||
|
||||
String string = (String) replaceMethod.invoke("jovo", 'o', 'a');
|
||||
|
||||
assertEquals("java", string);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenReplaceMethodHandle_whenInvoked_thenCorrectlyReplaced() throws Throwable {
|
||||
MethodHandles.Lookup publicLookup = MethodHandles.publicLookup();
|
||||
MethodType mt = MethodType.methodType(String.class, char.class, char.class);
|
||||
MethodHandle replaceMH = publicLookup.findVirtual(String.class, "replace", mt);
|
||||
|
||||
String replacedString = (String) replaceMH.invoke("jovo", Character.valueOf('o'), 'a');
|
||||
|
||||
assertEquals("java", replacedString);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenReplaceMethodHandle_whenInvokingExact_thenCorrectlyReplaced() throws Throwable {
|
||||
MethodHandles.Lookup lookup = MethodHandles.lookup();
|
||||
MethodType mt = MethodType.methodType(String.class, char.class, char.class);
|
||||
MethodHandle replaceMH = lookup.findVirtual(String.class, "replace", mt);
|
||||
|
||||
String s = (String) replaceMH.invokeExact("jovo", 'o', 'a');
|
||||
|
||||
assertEquals("java", s);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenSumMethodHandle_whenInvokingExact_thenSumIsCorrect() throws Throwable {
|
||||
MethodHandles.Lookup lookup = MethodHandles.lookup();
|
||||
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);
|
||||
}
|
||||
|
||||
@Test(expected = WrongMethodTypeException.class)
|
||||
public void givenSumMethodHandleAndIncompatibleArguments_whenInvokingExact_thenException() throws Throwable {
|
||||
MethodHandles.Lookup lookup = MethodHandles.lookup();
|
||||
MethodType mt = MethodType.methodType(int.class, int.class, int.class);
|
||||
MethodHandle sumMH = lookup.findStatic(Integer.class, "sum", mt);
|
||||
|
||||
sumMH.invokeExact(Integer.valueOf(1), 11);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenSpreadedEqualsMethodHandle_whenInvokedOnArray_thenCorrectlyEvaluated() throws Throwable {
|
||||
MethodHandles.Lookup publicLookup = MethodHandles.publicLookup();
|
||||
MethodType mt = MethodType.methodType(boolean.class, Object.class);
|
||||
MethodHandle equalsMH = publicLookup.findVirtual(String.class, "equals", mt);
|
||||
|
||||
MethodHandle methodHandle = equalsMH.asSpreader(Object[].class, 2);
|
||||
|
||||
assertTrue((boolean) methodHandle.invoke(new Object[] { "java", "java" }));
|
||||
assertFalse((boolean) methodHandle.invoke(new Object[] { "java", "jova" }));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenConcatMethodHandle_whenBindToAString_thenCorrectlyConcatenated() throws Throwable {
|
||||
MethodHandles.Lookup publicLookup = MethodHandles.publicLookup();
|
||||
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!"));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue