Java常见动态性的两种实现方式:
字节码操作(效率高一点)
反射
使用javassist库
局限性:
jdk5.0新语法不支持(包括泛型、枚举)、不支持注解修改,但可以通过底层javassist类库解决具体参见:javassist.bytecode.annotation
不支持数组的初始化,如string[]{"1","2"},除非数组的容量为1
不支持内部类和匿名类
不支持continue和break表达式
对于继承关系,有些不支持,例如
class A{}
class B extends A{]
class C extends B{}
import javassist.*;
import java.io.IOException;
/**
* 字节码操作
* 创建方法、属性、构造器
*/
public class Demo01 {
public static void main(String[] args) throws CannotCompileException, NotFoundException, IOException {
ClassPool pool=ClassPool.getDefault();
CtClass cc=pool.makeClass("com.assist.Emp");
//创建属性
CtField f1=CtField.make("private int id;",cc);
CtField f2=CtField.make("private String name;",cc);
cc.addField(f1);
cc.addField(f2);
//创建方法
CtMethod m1=CtMethod.make("public int getId(){return id;}",cc);
CtMethod m2=CtMethod.make("public String getName(){return name;}",cc);
cc.addMethod(m1);
cc.addMethod(m2);
//创建构造器
CtConstructor c=new CtConstructor(new CtClass[]{CtClass.intType,pool.get("java.lang.String")},cc);
c.setBody("{this.id=id;this.name=name;}");
cc.addConstructor(c);
cc.writeFile("D:/t");//将构造好的类写入
System.out.println("构造成功!");
}
}
测试Javassist的API
import javassist.*;
import javassist.bytecode.AccessFlag;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
/**
* 测试Javassist的API
*/
public class Demo02 {
/**
* 处理类的基本方法
*/
public static void test01() throws NotFoundException {
ClassPool pool=ClassPool.getDefault();
CtClass cc=pool.get("com.assist.Person");
//获得信息
System.out.println(cc.getName());
System.out.println(cc.getSimpleName());//不带包名的类名
System.out.println(cc.getSuperclass());
System.out.println(cc.getInterfaces());
}
/**
* 创建方法
* 调用方法
* @throws NotFoundException
* @throws CannotCompileException
* @throws NoSuchMethodException
* @throws InvocationTargetException
* @throws IllegalAccessException
* @throws InstantiationException
*/
public static void test02() throws NotFoundException, CannotCompileException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
ClassPool pool=ClassPool.getDefault();
CtClass cc=pool.get("com.assist.Person");
//创建方法
//CtMethod m=CtMethod.make("public int add(int a,int b){ return a+b}",cc);
//第二种方法
CtMethod m=new CtMethod(CtClass.intType,"add",new CtClass[]{CtClass.intType,CtClass.intType},cc);
m.setBody("{System.out.println(\"牛逼了你\");return $1+$2;}");
m.setModifiers(AccessFlag.PUBLIC);
cc.addMethod(m);
//使用反射调用新生成的方法
Class s=cc.toClass();
Object obj=s.newInstance();
Method method=s.getDeclaredMethod("add",int.class,int.class);
Object result=method.invoke(obj,2,3);
System.out.println(result);
}
/**
* 在方法中加入内容
* @throws NotFoundException
* @throws CannotCompileException
* @throws IllegalAccessException
* @throws InstantiationException
* @throws NoSuchMethodException
* @throws InvocationTargetException
*/
public static void test03() throws NotFoundException, CannotCompileException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
ClassPool pool=ClassPool.getDefault();
CtClass cc=pool.getCtClass("com.assist.Person");
//获得方法
CtMethod method=cc.getDeclaredMethod("haha",new CtClass[]{CtClass.intType});
method.insertBefore("System.out.println(\"你好啊!\");");
method.insertAt(7,"System.out.println(\"我进来了\");");
method.insertAfter("System.out.println(\"拜拜\");");
//使用反射调用方法
Class ss=cc.toClass();
Object obj=ss.newInstance();
Method method1=ss.getMethod("haha",int.class);
method1.invoke(obj,300);
}
/**
* 创建属性
* 获得属性
* @throws NotFoundException
* @throws NoSuchMethodException
* @throws CannotCompileException
* @throws IllegalAccessException
* @throws InvocationTargetException
* @throws InstantiationException
*/
public static void test04() throws NotFoundException, CannotCompileException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
ClassPool pool=ClassPool.getDefault();
CtClass cc=pool.get("com.assist.Person");
//创建属性
//CtField field=CtField.make("private int salary=10000;",cc);
CtField field=new CtField(CtClass.intType,"salary",cc);
field.setModifiers(Modifier.PRIVATE);
cc.addField(field,"1000");
// System.out.println(cc.getDeclaredField("salary"));
//添加get方法
cc.addMethod(CtNewMethod.getter("getSalary",field));
cc.addMethod(CtNewMethod.setter("setSalary",field));
//反射调用方法
Class ss=cc.toClass();
Object obj=ss.newInstance();//记得调用构造器
Method method=ss.getDeclaredMethod("getSalary");
Method method1=ss.getDeclaredMethod("setSalary",int.class);
method1.invoke(obj,10000000);
System.out.println(method.invoke(obj));
}
/**
* 获得构造器
* @throws NotFoundException
* @throws NoSuchMethodException
* @throws CannotCompileException
* @throws IllegalAccessException
* @throws InvocationTargetException
* @throws InstantiationException
*/
public static void test05() throws NotFoundException {
ClassPool pool=ClassPool.getDefault();
CtClass cc=pool.get("com.assist.Person");
//获得构造器
for (CtConstructor c: cc.getConstructors()
) {
System.out.println(c);
}
}
//获得注解
public static void test06() throws ClassNotFoundException, NotFoundException {
ClassPool pool=ClassPool.getDefault();
CtClass cc=pool.get("com.assist.Person");
Object[] objects=cc.getAnnotations();
Test test=(Test)objects[0];
System.out.println(test.name()+": "+test.age()+"岁");
}
public static void main(String[] args) throws NotFoundException, NoSuchMethodException, CannotCompileException, IllegalAccessException, InvocationTargetException, InstantiationException {
test04();
}
}