我坚持使用javassist.我在运行时向对象类添加了一个新方法.
我的对象类:
package tmp3;
public class Car {
public Car(){}
}
Run Code Online (Sandbox Code Playgroud)
我的考试班:
package tmp3;
import java.lang.reflect.Method;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.CtNewMethod;
public class TestMain {
public static void main(String[] args) {
try {
CtClass ctclass = ClassPool.getDefault().get("tmp3.Car");
CtMethod newmethod = CtNewMethod.make("public void testPrint() { System.out.println(\"test ok\"); }",ctclass);
ctclass.addMethod(newmethod);
ctclass.writeFile();
for(Method me: ctclass.toClass().getDeclaredMethods()){ //test print, ok
System.out.println(me.getName());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Run Code Online (Sandbox Code Playgroud)
但在那之后,我不知道如何调用(调用)它.我已经读过javassist没有能力调用方法.那我怎么能调用我刚刚用javassist添加的方法呢?
我在两天内尝试过很多东西但没有成功.你能帮帮我吗?
Java类具有静态接口,这意味着,正如您可能已经知道的那样,Java在默认情况下并未设计为在运行时向类添加方法,因此它有点棘手,但并不难以实现您想要的.
您已经使用Javassist(字节码修饰符框架)来设计编译的类以添加更多代表新方法的字节码.您可以拥有以下两种方案之一:
在这种情况下,在编译代码时,Java编译器只知道Car接口而不进行任何注入.所以你不能直接调用注入的方法,如下所示:
Car car = new Car();
car.testPrint();
Run Code Online (Sandbox Code Playgroud)
你必须像@Scorpion这样的反思正确评论:
Car car = new Car();
Method method = car.getClass().getMethod("testPrint", new Class[]{});
method.invoke(car,new Object[]{});
Run Code Online (Sandbox Code Playgroud)
但这不是唯一的方法......
如果你编译你的Car类,注入它,然后针对编译的类编写代码(例如Car在jar文件中有类),你将能够调用你的注入方法,就像它是任何其他常规方法一样.
做以下练习:
Car课程Car实例的类,注意您现在可以毫无困难地调用testPrint方法.你应该注意的一些事情:
java.lang.ClassFormatError错误消息,指出您有一个Truncated Class文件.如果Javassist没有将所有字节码加载到内存并尝试对同一类文件进行写入和读取,则会发生这种情况,这会导致完全混乱.为避免这种情况,您可以写入其他路径,也可以确保在写入文件之前将所有字节码加载到内存中(使用toByteCode()from CtClass).