Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java: Generate custom Java code at compile time using annotations

Tags:

java

java-8

How do I write a Java inner class with custom properties at compile time using annotations?

For instance, I want this :

@Generate
class Person {
     String firstname, lastname;
}

to generate:

class Person {
    String firstname, lastname;

    public static class $Fields { 
           public static String firstname = "firstname";
           public static String lastname  = "lastname";
    } 
}

How can I write the interface:

@Retention(RetentionPolicy.SOURCE)
public @interface Generate {
     // ... 
}

I understand I need to do some kind of AST transformation to make this magical.

I am also aware of project lombok, but I want to know what the least common denominator is with a simple example, preferably within one method, and preferably something that a good editor would consider automatically, for instance RetentionPolicy.SOURCE for the javac compiler, which can be used in Intellij IDEA.

Project lombok is a beast code wise and is tough place to start.

It must be simpler than that, is it not?

Any ideas?

like image 336
mjs Avatar asked Sep 23 '14 20:09

mjs


Video Answer


1 Answers

You can do this by reflection, but your new class won't be an inner class; but be warned, you will lose static type safety.

It can be done in 2 steps:

  1. Read the annotated class via reflection and transform it into a String which represents the source code of your new class.
  2. Write this string to file, compile this String using the Java compiler API and then load and instantiate the new class, all programatically; see exact steps here.

Alternatives to achieving similar functionality can also be obtained by bytecode instrumentation (see cglib or javassist) or maybe even with proxies.

like image 73
Random42 Avatar answered Nov 15 '22 21:11

Random42