Created
September 1, 2016 22:08
-
-
Save edefazio/e78cd776e72e6832a30821df247d1df0 to your computer and use it in GitHub Desktop.
Java metaprogramming using JavaPoet to generate .java source and the varcode InMemoryJavacCompiler
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package ex.javapoet; | |
import java.io.IOException; | |
import java.util.ArrayList; | |
import java.util.List; | |
import java.util.Map; | |
import javax.lang.model.element.Modifier; | |
import com.squareup.javapoet.JavaFile; | |
import com.squareup.javapoet.MethodSpec; | |
import com.squareup.javapoet.TypeSpec; | |
import varcode.java.Java; | |
import varcode.java.javac.InMemoryJavaClassLoader; | |
import varcode.java.javac.InMemoryJavaCode; | |
import varcode.java.javac.InMemoryJavac; | |
/**<PRE> | |
* | |
* *1* build a main method | |
* *2* build a class and add the main method | |
* *3* build a (.java) file | |
* *4* write the (.java) file to System.out | |
* *5* prepare file to be compiled by javac | |
* *6* compile and load the (.class) from the (.java) file | |
* *7* invoke the main method on the (.class) | |
*/ | |
public class JavaPoetHelloWorldMeta | |
{ | |
public static void main(String[] args) throws IOException | |
{ | |
MethodSpec main = MethodSpec.methodBuilder("main") // *1* | |
.addModifiers(Modifier.PUBLIC, Modifier.STATIC) | |
.returns(void.class) | |
.addParameter(String[].class, "args") | |
.addStatement("$T.out.println($S)", System.class, "Hello, JavaPoet!") | |
.build(); | |
TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld") // *2* | |
.addModifiers(Modifier.PUBLIC, Modifier.FINAL) | |
.addMethod(main) | |
.build(); | |
JavaFile javaFile = | |
JavaFile.builder("ex.javapoet", helloWorld) | |
.build(); // *3* | |
javaFile.writeTo( System.out ); // *4* | |
List<InMemoryJavaCode> toCompile = // *5* | |
new ArrayList<InMemoryJavaCode>(); | |
toCompile.add( | |
InMemoryJavaCode.of( javaFile.toJavaFileObject() ) ); // *5* | |
Map<String,Class<?>> classNameToClass = // *5* *6* | |
InMemoryJavac.compileLoadClasses( | |
new InMemoryJavaClassLoader(), | |
toCompile ); | |
Class<?> clazz = | |
classNameToClass.get( "ex.javapoet.HelloWorld" ); | |
Java.invoke( clazz, "main", (Object)new String[ 0 ] ); // *7* | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Metaprogramming Java (HelloWorld) Examples:
*IMPORTANT NOTE: all examples REQUIRE a Runtime JDK (not a JRE) to compile
Java Code (.java files) to .class files at runtime. (and varcode) *
varcode JavaModel
varcode CodeML
varcode BindML
JavaPoet / varcode
varcode (and in particular varcode JavaModel) makes metaprogramming easy by composing Java source files in a way that is natural and intuitive.
varcode is easy to write, use, test, modify and maintain (it looks just like the Java code you already know.)
Alternatively JavaPoet is clunky, because:
it requires manual code to call the Java Compiler.
generated code "does", therefore it's harder to learn, use, test, and maintain.
Having the ability to easily invoke the Javac compiler with a simple method makes iteration and testing MUCH easier with varcode)