日期:2014-05-16  浏览次数:20413 次

JSR 292 的用法 (MethodHandle...)
用例转自:http://code.google.com/p/jsr292-cookbook/


Constants
?lazy initialization

package jsr292.cookbook.lazyinit;

import java.io.IOException;
import java.lang.invoke.CallSite;
import java.lang.invoke.ConstantCallSite;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodHandles.Lookup;
import java.lang.invoke.MethodType;
import java.nio.ByteBuffer;

import sun.misc.BASE64Decoder;

public class RT {
  @SuppressWarnings("restriction")
  public static CallSite bootstrap(Lookup lookup, String name, MethodType type, String base64Array) throws IOException {
    BASE64Decoder decoder = new BASE64Decoder();
    byte[] bytes = decoder.decodeBuffer(base64Array);
    
    Class<?> returnType = type.returnType();
    Object value = convertAsArray(bytes, returnType);
    return new ConstantCallSite(MethodHandles.constant(returnType, value));
  }
  
  private static Object convertAsArray(byte[] bytes, Class<?> returnType) {
    if (returnType == byte[].class) {
      return bytes;
    } else
      if (returnType == char[].class) {
        char[] array = new char[bytes.length / 2];
        ByteBuffer.wrap(bytes).asCharBuffer().get(array);
        return array;
      } else
        if (returnType == short[].class) {
          return ByteBuffer.wrap(bytes).asShortBuffer().duplicate().array();
        } else
          if (returnType == int[].class) {
            return ByteBuffer.wrap(bytes).asIntBuffer().duplicate().array();
          } else
            if (returnType == long[].class) {
              return ByteBuffer.wrap(bytes).asLongBuffer().duplicate().array();
            } else
              if (returnType == float[].class) {
                return ByteBuffer.wrap(bytes).asFloatBuffer().duplicate().array();
              } else
                if (returnType == double[].class) {
                  return ByteBuffer.wrap(bytes).asDoubleBuffer().duplicate().array();
                } else {
                  throw new BootstrapMethodError("invalid constant array type "+returnType);
                }
  }
}

Method handle interceptors
?before, after
?try/finally

package jsr292.cookbook.interceptors;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
//import java.util.Map;

public class Interceptors {
  
  public static MethodHandle before(MethodHandle target, MethodHandle before) {
    MethodType beforeType = before.type();
    if (beforeType.returnType() != void.class) {
      throw new IllegalArgumentException("before must return void "+beforeType);
    }
    MethodType targetType = target.type();
    if (beforeType.parameterCount() != targetType.parameterCount()) {
      if (beforeType.parameterCount() > targetType.parameterCount()) {
        throw new IllegalArgumentException("before has too much parameter compare to target "+beforeType+" "+targetType);
      }
      before = MethodHandles.dropArguments(before,
          beforeType.parameterCount(),
          targetType.parameterList().subList(beforeType.parameterCount(), targetType.parameterCount()));  
    }
    
    if (!before.type().equals(targetType.changeReturnType(void.class))) {
      throw new IllegalArgumentException("before parameter types are not compatible with target "+beforeType+" "+targetType);
    }
    
    return MethodHandles.foldArguments(target, before);
  }
  
  public static MethodHandle after(MethodHandle target, MethodHandle after) {
    //FIXME just use filterReturnValue instead !!, when bug fixed
    
    MethodType afterType = after.type();
    if (afterType.returnType() != void.class) {
      throw new IllegalArgumentException("after must return void "+afterType);
    }
    
    MethodType targetType = target.type();
    boolean voidReturnType = targetType.returnType() == v