- 可变参数的方法反射调用需要注意,参数强转
/**
* @program: spring-data-jpa-demo
* @author: whp
* @create: 2020-01-06 23:06
**/
public class VarargsConstruct {
public VarargsConstruct(String...names){
System.out.println("反射调用"+names.length);
};
public VarargsConstruct(Integer...num){
System.out.println("反射调用"+num.length);
};
/**
* 可变参数的反射需要注意需要将数组强转型为object,否则会报参数数字不正确
* @return: void
* @Author: whp
* @Date: 1/7/2020
*/
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Constructor<VarargsConstruct> constructor = VarargsConstruct.class.getDeclaredConstructor(String[].class);
Constructor<VarargsConstruct> constructor1 = VarargsConstruct.class.getDeclaredConstructor(Integer[].class);
constructor.newInstance((Object) new String[]{"a","b"});
constructor1.newInstance((Object)new Integer[]{1,2,3});
}
}
- 静态内部类的反射调用
/**
* @program: spring-data-jpa-demo
* @author: whp
* @create: 2020-01-06 23:32
**/
public class StaticNestedClass {
public StaticNestedClass(String name){}
class NestedClass{
public NestedClass(int count){
System.out.println(count);
}
}
/**
* 反射获取静态内部类时,需要注意构造器第一个参数是外部类的class,构造器调用时第一个参数是this
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
Constructor<StaticNestedClass> sncc = StaticNestedClass.class.getDeclaredConstructor(String.class);
StaticNestedClass instance = sncc.newInstance("name");
Constructor<NestedClass> constructor = NestedClass.class.getDeclaredConstructor(StaticNestedClass.class, int.class);
NestedClass ic = constructor.newInstance(instance, 3);
}
}
方法句柄
他是JSR -292引入的重要概念,是对java中方法,构造方法和域的可执行引用,通过方法句柄可以直接调用该句柄所引用的底层方法,类似于反射,但是比放射更加灵活
方法句柄的类型完全由参数类型和返回类型确定
//获取方法句柄
public void lookupMethod() throws NoSuchMethodException, IllegalAccessException {
MethodHandles.Lookup lookup = MethodHandles.lookup();
//string的构造器句柄
MethodHandle constructor = lookup.findConstructor(String.class, MethodType.methodType(void.class, byte[].class));
//String.subString
MethodHandle subString = lookup.findVirtual(String.class, "subString", MethodType.methodType(String.class, int.class, int.class));
//String.format
MethodHandle format = lookup.findStatic(String.class, "format", MethodType.methodType(String.class, String.class, Object[].class));
}
invokedynamic指令
- invokestatic,invokespecial,invokevirtual,invokeinterface四种指令只支持方法调用时的单派发(即实际调用时对方法的选择只会根据调用的就收者不同而不同),更贴切的说只对invokevirtual,invokeinterface起作用
- invokedynamic指令就是弥补这种不足,即支持方法调用的多派发
- invokedynamic只是一个字节码指令,传统的编译器不会帮开发人员生成该指令,需要开发人员自己来生成包含这个指令的java代码