title: Some basic questions about MethodHandle API
body: <p>How can I obtain all declared method through <code>MethodHandles.lookup()</code>? How can I obtain all declared fields?</p>
  
  <p>What is difference betweeen <code>MethodHandle.invoke()</code>, <code>MethodHandle.invokeExact()</code> and <code>MethodHandle.invokeWithArguments()</code></p>
  
  <p>Also, I will be appreciate for tutorial about using MethodHandle API for <strong>Java devloper</strong>. I emphasize, I am programming on statically typed language plain old Java and I am not JVM developer, particularly I am not interesting with whole byte-code crap (invokedynamic). I want to figure out how can I use this new API instead of Java Core API.</p>
  
  <p><strong>EDITED-2:</strong></p>
  
  <p>@Glen Best below provided some refferences I want to provide only one <a href="http://www.oraclejavamagazine-digital.com/javamagazine/20130102?pg=52&amp;search_term=methodhandle&amp;doc_id=-1#pg50" rel="noreferrer">http://www.oraclejavamagazine-digital.com/javamagazine/20130102?pg=52&amp;search_term=methodhandle&amp;doc_id=-1#pg50</a> This is exactly what I was looking for. I figured out that actually there some new vocabalry.. For example, by <em>target</em> is actually meant MethodHandle (and not object to make dispatch upon) and <em>call site</em> is actually code that "invokes" "function pointer" aka MethodHandle. Also it is essential to understand that MethodHandle API is <strong>not replacement for</strong> Core Reflection API rather than <em>suplement</em> it. For example, you can't "discover" all methods with MethodHandle you need Core Reflection API. But when you "find" you desired method you can switch to MethodHandle and for example, bound some its parameters or "change" (adapt) it's signature to varargs for example. </p>
  
  <p><strong>EDITED:</strong></p>
  
  <p>I am still trying to figure out answer. I wrote some tests that I want to share with all.</p>
  
  <pre><code>package alexander.berkovich;
  
  import static org.junit.Assert.assertSame;
  
  import java.lang.invoke.MethodHandle;
  import java.lang.invoke.MethodHandles;
  import java.lang.invoke.MethodType;
  import java.lang.reflect.Field;
  import java.lang.reflect.Method;
  
  import org.junit.BeforeClass;
  import org.junit.Test;
  
  public class MethodHandlerCleanTest {
  
      public static MethodHandles.Lookup lookup;
  
      @BeforeClass
      public static void asetUp(){
          lookup = MethodHandles.lookup();
      }
  
      public static class Check {
          public void primitive(final int i){
          }
          public void wrapper(final Integer i){
          }
      }
  
      @Test
      public void testPrimitive() throws Throwable {
          Check check = new Check();
  
          MethodType type = MethodType.methodType(void.class, int.class);
  
          MethodHandle mh = lookup.findVirtual(Check.class, "primitive", type);
          mh.invokeWithArguments(check, 1);
          mh.invoke(check, (short)2);
          mh.invoke(check, Integer.valueOf(3));
  
          Method method = Check.class.getMethod("primitive", int.class);
          method.invoke(check, (short)20);
          method.invoke(check, Integer.valueOf(21));
  
      }
  
      @Test
      public void testWrapper() throws Throwable {
          Check check = new Check();
  
          MethodType type = MethodType.methodType(void.class, Integer.class);
  
          MethodHandle mh = lookup.findVirtual(Check.class, "wrapper", type);
          mh.invoke(check, 2);
  
          Method method = Check.class.getMethod("wrapper", Integer.class);
          method.invoke(check, 20);
  
      }
  
      @SuppressWarnings("unused")
      public static class StaticInnerClass {
  
          public static String staticName;
          public String name;
  
  
          public void foo(){}
  
          public static void staticFoo(){}
  
      }
  
      @Test
      public void testStaticInnerClassStaticField() throws Throwable {
          MethodHandle mhSet = lookup.findStaticSetter(StaticInnerClass.class, "staticName", String.class);
          String expected = "mama";
          mhSet.invoke(expected);
  
          MethodHandle mhGet = lookup.findStaticGetter(StaticInnerClass.class, "staticName", String.class);
          Object obj = mhGet.invoke();
          String value = (String)obj;
          assertSame(expected, value);
  
      }
  
      @Test
      public void testStaticInnerClassField() throws Throwable {
          StaticInnerClass sut = new StaticInnerClass();
          Field f = StaticInnerClass.class.getDeclaredField("name");
          MethodHandle mhSetUnreflect = lookup.unreflectSetter(f); 
          String expectedUnreflect = "unreflect";
          mhSetUnreflect.invoke(sut, expectedUnreflect);
  
  
          MethodHandle mhSet = lookup.findSetter(StaticInnerClass.class, "name", String.class);
          String expected = "mama";
          mhSet.invoke(sut, expected);
  
          MethodHandle mhGet = lookup.findGetter(StaticInnerClass.class, "name", String.class);
          Object obj = mhGet.invoke(sut);
          String value = (String)obj;
          assertSame(expected, value);
  
      }
  
      @Test
      public void testStaticInnerClassConstructor() throws Throwable {
          StaticInnerClass sut = new StaticInnerClass();
          MethodType type = MethodType.methodType(void.class);
          MethodHandle mh = lookup.findConstructor(StaticInnerClass.class, type);
          mh.invoke();
      }
  
      @Test
      public void testStaticInnerClassMethod() throws Throwable {
          StaticInnerClass sut = new StaticInnerClass();
          MethodType type = MethodType.methodType(void.class);
          MethodHandle mh = lookup.findVirtual(StaticInnerClass.class, "foo", type);
          mh.invoke(sut);
      }
  
      @Test
      public void testStaticInnerClassStaticMethod() throws Throwable {
          MethodType type = MethodType.methodType(void.class);
          MethodHandle mh = lookup.findStatic(StaticInnerClass.class, "staticFoo", type);
          mh.invoke();
      }
  
      @SuppressWarnings("unused")
      private class InnerClass {
          public String name;
  
          public void foo(){}
  
      }
      @Test
      public void testInnerClassField() throws Throwable {
          InnerClass sut = new InnerClass();
          MethodHandle mhSet = lookup.findSetter(InnerClass.class, "name", String.class);
          String expected = "mama";
          mhSet.invoke(sut, expected);
  
          MethodHandle mhGet = lookup.findGetter(InnerClass.class, "name", String.class);
          Object obj = mhGet.invoke(sut);
          String value = (String)obj;
          assertSame(expected, value);
  
      }
  
  
      @Test
      public void testInnerClassConstructor() throws Throwable {
          MethodType type = MethodType.methodType(void.class, MethodHandlerCleanTest.class);
  
          //default constructor is private
          Field field = MethodHandles.Lookup.class.getDeclaredField("IMPL_LOOKUP");
          field.setAccessible(true);
          MethodHandles.Lookup trustedLookup = (MethodHandles.Lookup) 
                  field
                  .get(null);
  
          MethodHandle mh = trustedLookup.findConstructor(InnerClass.class, type);
          mh.invoke(this);
      }
  
  
      @Test
      public void testInnerClassMethod() throws Throwable {
          InnerClass sut = new InnerClass();
          MethodType type = MethodType.methodType(void.class);
          MethodHandle mh = lookup.findVirtual(InnerClass.class, "foo", type);
          mh.invoke(sut);
      }
  </code></pre>
  
  <p>}</p>