Javassist: creating an interface that extends another interface with generics

断了今生、忘了曾经 提交于 2019-11-29 05:18:22

Short Answer

The generic information can be manipulated in Javassist using the SignatureAttribute.

Long answer (with code)

The code you probably already have is something like this:

 ClassPool defaultClassPool = ClassPool.getDefault();
 CtClass superInterface = defaultClassPool.getCtClass(CrudRepository.class
            .getName());
 CtClass catRepositoryInterface = defaultClassPool.makeInterface("CatRepository", ctClass);

// something is missing here :-(

 catRepositoryInterface.toClass()

But, like you already said this will not add the information about generics. In order to achieve the same bytecode you would get from compiling the source code, you need to do the following where the comment is:

SignatureAttribute signatureAttribute = new SignatureAttribute(
            classFile.getConstPool(),
     "Ljava/lang/Object;Lorg/springframework/data/repository/CrudRepository<Lorg/example/Cat;Ljava/lang/Long;>;");
ClassFile metaInformation = catRepositoryInterface.getClassFile();
classFile.addAttribute(signatureAttribute);

Let's break down the signature string in order to understand what's happening there:

  • You see several L[TYPE], what is it? L is the standard notation in bytecode to define an Object Class, you can read more about this if you're interested in the JVM Specification regarding descriptors

  • ';' is being used as a separator between several definitions. Let's look at each one of them:

    • Ljava/lang/Object
    • Lorg/springframework/data/repository/CrudRepository<Lorg/example/Cat;Ljava/lang/Long;>

The first definition has to be there because in the Java language everything extends from java.lang.Object (doesn't matter if class or interface).

But the most interesting one is the second one, there you have your type with the full classname and the generic types definitions, everything using the L notation. That's what you are missing :-)


Note

Keep in mind that if you want to extend from more than one interface, you just have to add them in the list for example, the following signature would make the interface not only extend from CrudRepository but also from Serializable:

Ljava/lang/object;Lorg/springframework/data/repository/CrudRepository<Lorg/example/Cat;Ljava/lang/Long;>;**Ljava/io/Serializable;**
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!