I´m trying to create a class with javassit that implements a generic interface passing the generic argument but without sucess so far.
I´m aware of the answer Javassist: creating an interface that extends another interface with generics and the javassit tutorial but none of those helped.
Here is my code:
String met = "public void doit(com.package.Pojo o) { System.out.println(\"Result: \" + o.getName()); }";
ClassPool cp = ClassPool.getDefault();
CtClass cc = cp.makeClass("Teste");
cc.setInterfaces(new CtClass[]{cp.get("com.package.Factor")});
ClassSignature cs = new ClassSignature(null, null,
// Set interface and its generic params
new ClassType[]{new ClassType("com.package.Factor",
new TypeArgument[]{new TypeArgument(new ClassType("com.package.Pojo"))}
)});
cc.setGenericSignature(cs.encode());
//cc.setGenericSignature("Ljava/lang/Object;Lcom/aurora/core/util/Factor<Lcom/aurora/core/util/Pojo;>;");
CtMethod make = CtNewMethod.make(met, cc);
cc.addMethod(make);
Class<Factor<Pojo>> class1 = cc.toClass();
Factor<Pojo> obj = (Factor<Pojo>) class1.newInstance();
obj.doit(new Pojo("name here"));
Factor class:
public interface Factor<T> {
void doit(T ent);
}
My pom
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.20.0-GA</version>
</dependency>
And the error:
Exception in thread "main" java.lang.AbstractMethodError: Teste.doit(Ljava/lang/Object;)V at com.package.Main3.main(Main3.java:40)
Thanks in advance !
The Java runtime works with type erasure. Therefore, the doit(T)
method is defined as doit(java.lang.Object)
in the interface type. In order to override a method, you need to implement it in the generated class. The Java compiler does this for you transparently when you define a method, javassist does not do it for you.
Therefore, you need to add a so-called bridge method that invokes the actual method but that overrides the interface's method:
public void doit(Object ent) {
doit((Pojo) ent);
}