Hi, welcome to the second edition of Last Week in Objectos (LWO).
In this edition I will discuss:
- a few of my findings about the Java language while working on Objectos Code; and
- the last week’s work on Objectos Code itself.
Let’s begin.
Annotations are just modifiers (grammatically speaking)
I didn’t know that, grammatically (syntactically?) speaking, annotations are just modifiers to the Java language. In other words, I have always thought that the only way to annotate, say a method, would be:
<span>@Override</span><span>public</span> <span>final</span> <span>String</span> <span>toString</span><span>()</span> <span>{</span><span>return</span> <span>"Annotations are just modifiers"</span><span>;</span><span>}</span><span>@Override</span> <span>public</span> <span>final</span> <span>String</span> <span>toString</span><span>()</span> <span>{</span> <span>return</span> <span>"Annotations are just modifiers"</span><span>;</span> <span>}</span>@Override public final String toString() { return "Annotations are just modifiers"; }
Enter fullscreen mode Exit fullscreen mode
But, in fact, you can write:
<span>public</span> <span>@Override</span> <span>final</span> <span>String</span> <span>toString</span><span>()</span> <span>...</span><span>public</span> <span>@Override</span> <span>final</span> <span>String</span> <span>toString</span><span>()</span> <span>...</span>public @Override final String toString() ...
Enter fullscreen mode Exit fullscreen mode
Or, if you prefer:
<span>public</span> <span>final</span> <span>@Override</span> <span>String</span> <span>toString</span><span>()</span> <span>...</span><span>public</span> <span>final</span> <span>@Override</span> <span>String</span> <span>toString</span><span>()</span> <span>...</span>public final @Override String toString() ...
Enter fullscreen mode Exit fullscreen mode
I always thought that the last two examples would fail to compile. But they do not; all of the three declarations are syntactically correct.
Additionally, all of the three declarations are equivalent. Well, there is a small caveat in the last example regarding type annotations, which we’ll look into at another time.
I found out about it when reading the grammar production of method declarations:
MethodDeclaration:{MethodModifier} MethodHeader MethodBodyMethodDeclaration: {MethodModifier} MethodHeader MethodBodyMethodDeclaration: {MethodModifier} MethodHeader MethodBody
Enter fullscreen mode Exit fullscreen mode
It means that a method declaration can contain zero or more MethodModifier
. The MethodModifier
production is defined as:
MethodModifier:(one of)Annotation public protected privateabstract static final synchronized native strictfpMethodModifier: (one of) Annotation public protected private abstract static final synchronized native strictfpMethodModifier: (one of) Annotation public protected private abstract static final synchronized native strictfp
Enter fullscreen mode Exit fullscreen mode
So any of the modifiers can appear in any order. Cool!
An Array Access Expression curiosity
Array access expressions are expressions to, well, access a component of an array.
A simple example can be:
<span>String</span><span>[]</span> <span>a</span> <span>=</span> <span>{</span> <span>"array"</span><span>,</span> <span>"access"</span> <span>};</span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>a</span><span>[</span><span>1</span><span>]);</span><span>String</span><span>[]</span> <span>a</span> <span>=</span> <span>{</span> <span>"array"</span><span>,</span> <span>"access"</span> <span>};</span> <span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>a</span><span>[</span><span>1</span><span>]);</span>String[] a = { "array", "access" }; System.out.println(a[1]);
Enter fullscreen mode Exit fullscreen mode
The argument to the println
method, i.e. the a[1]
, is an array access expression.
The following is wrong and does not compile:
<span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>this</span><span>[</span><span>1</span><span>]);</span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>this</span><span>[</span><span>1</span><span>]);</span>System.out.println(this[1]);
Enter fullscreen mode Exit fullscreen mode
But why does it not compile? Well, that’s what is curious to me. I thought it failed to compile simply because the “syntax is invalid”. But that is not exactly what happens in this case.
Let’s try to compile and run the following program:
<span>public</span> <span>class</span> <span>Test</span> <span>{</span><span>public</span> <span>static</span> <span>void</span> <span>main</span><span>(</span><span>String</span><span>[]</span> <span>args</span><span>)</span> <span>{</span><span>new</span> <span>Test</span><span>().</span><span>execute</span><span>();</span><span>}</span><span>public</span> <span>void</span> <span>execute</span><span>()</span> <span>{</span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>this</span><span>[</span><span>1</span><span>]);</span><span>}</span><span>}</span><span>public</span> <span>class</span> <span>Test</span> <span>{</span> <span>public</span> <span>static</span> <span>void</span> <span>main</span><span>(</span><span>String</span><span>[]</span> <span>args</span><span>)</span> <span>{</span> <span>new</span> <span>Test</span><span>().</span><span>execute</span><span>();</span> <span>}</span> <span>public</span> <span>void</span> <span>execute</span><span>()</span> <span>{</span> <span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>this</span><span>[</span><span>1</span><span>]);</span> <span>}</span> <span>}</span>public class Test { public static void main(String[] args) { new Test().execute(); } public void execute() { System.out.println(this[1]); } }
Enter fullscreen mode Exit fullscreen mode
When I try to run it:
$ java Test.javaTest.java:7: error: array required, but Test foundSystem.out.println(this[1]);^1 errorerror: compilation failed$ java Test.java Test.java:7: error: array required, but Test found System.out.println(this[1]); ^ 1 error error: compilation failed$ java Test.java Test.java:7: error: array required, but Test found System.out.println(this[1]); ^ 1 error error: compilation failed
Enter fullscreen mode Exit fullscreen mode
It fails to compile because this
does not evaluate to an array type. So, in some ways, the syntax itself is valid. But, as this
resolves to a non-array type, it fails to compile.
This is expected as it is defined in the language specification. The ArrayAccess
production is given by the following:
ArrayAccess:ExpressionName [ Expression ]PrimaryNoNewArray [ Expression ]ArrayCreationExpressionWithInitializer [ Expression ]ArrayAccess: ExpressionName [ Expression ] PrimaryNoNewArray [ Expression ] ArrayCreationExpressionWithInitializer [ Expression ]ArrayAccess: ExpressionName [ Expression ] PrimaryNoNewArray [ Expression ] ArrayCreationExpressionWithInitializer [ Expression ]
Enter fullscreen mode Exit fullscreen mode
We are interested in the second form, the one with PrimaryNoNewArray
. PrimaryNoNewArray
is defined as:
LiteralClassLiteralthisTypeName . this( Expression )ClassInstanceCreationExpressionFieldAccessArrayAccessMethodInvocationMethodReferenceLiteral ClassLiteral this TypeName . this ( Expression ) ClassInstanceCreationExpression FieldAccess ArrayAccess MethodInvocation MethodReferenceLiteral ClassLiteral this TypeName . this ( Expression ) ClassInstanceCreationExpression FieldAccess ArrayAccess MethodInvocation MethodReference
Enter fullscreen mode Exit fullscreen mode
So the following (wrong) examples:
<span>1234</span><span>[</span><span>0</span><span>];</span><span>Object</span><span>.</span><span>class</span><span>[</span><span>1</span><span>];</span><span>this</span><span>[</span><span>2</span><span>];</span><span>Outer</span><span>.</span><span>this</span><span>[</span><span>3</span><span>];</span><span>1234</span><span>[</span><span>0</span><span>];</span> <span>Object</span><span>.</span><span>class</span><span>[</span><span>1</span><span>];</span> <span>this</span><span>[</span><span>2</span><span>];</span> <span>Outer</span><span>.</span><span>this</span><span>[</span><span>3</span><span>];</span>1234[0]; Object.class[1]; this[2]; Outer.this[3];
Enter fullscreen mode Exit fullscreen mode
All fail to compile. But not because the “syntax is invalid”. Instead, they fail to compile because the part to left of the brackets do not evaluate to an array type.
Faux code generators
I am creating Objectos Code because I write a lot of code generators. But parts of Objectos Code itself might benefit of having them being generated. What to do in this case?
Well, I write a plain “faux” (ad-hoc?) code generator. It looks a bit like this:
<span>import</span> <span>static</span> <span>java</span><span>.</span><span>lang</span><span>.</span><span>System</span><span>.</span><span>out</span><span>;</span><span>public</span> <span>class</span> <span>ByteCodeFauxGenerator</span> <span>{</span><span>private</span> <span>int</span> <span>value</span> <span>=</span> <span>-</span><span>1</span><span>;</span><span>public</span> <span>static</span> <span>void</span> <span>main</span><span>(</span><span>String</span><span>[]</span> <span>args</span><span>)</span> <span>{</span><span>var</span> <span>gen</span> <span>=</span> <span>new</span> <span>ByteCodeFauxGenerator</span><span>();</span><span>gen</span><span>.</span><span>execute</span><span>();</span><span>}</span><span>public</span> <span>final</span> <span>void</span> <span>execute</span><span>()</span> <span>{</span><span>comment</span><span>(</span><span>"class"</span><span>);</span><span>value</span><span>(</span><span>"CLASS"</span><span>);</span><span>value</span><span>(</span><span>"MODIFIER"</span><span>);</span><span>value</span><span>(</span><span>"IDENTIFIER"</span><span>);</span><span>comment</span><span>(</span><span>"statements"</span><span>);</span><span>value</span><span>(</span><span>"LOCAL_VARIABLE"</span><span>);</span><span>value</span><span>(</span><span>"RETURN_STATEMENT"</span><span>);</span><span>}</span><span>private</span> <span>void</span> <span>comment</span><span>(</span><span>String</span> <span>string</span><span>)</span> <span>{</span><span>out</span><span>.</span><span>println</span><span>();</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"// "</span> <span>+</span> <span>string</span><span>);</span><span>out</span><span>.</span><span>println</span><span>();</span><span>}</span><span>private</span> <span>void</span> <span>value</span><span>(</span><span>String</span> <span>string</span><span>)</span> <span>{</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"static final int "</span> <span>+</span> <span>string</span> <span>+</span> <span>" = "</span> <span>+</span> <span>value</span><span>--</span> <span>+</span> <span>";"</span><span>);</span><span>}</span><span>}</span><span>import</span> <span>static</span> <span>java</span><span>.</span><span>lang</span><span>.</span><span>System</span><span>.</span><span>out</span><span>;</span> <span>public</span> <span>class</span> <span>ByteCodeFauxGenerator</span> <span>{</span> <span>private</span> <span>int</span> <span>value</span> <span>=</span> <span>-</span><span>1</span><span>;</span> <span>public</span> <span>static</span> <span>void</span> <span>main</span><span>(</span><span>String</span><span>[]</span> <span>args</span><span>)</span> <span>{</span> <span>var</span> <span>gen</span> <span>=</span> <span>new</span> <span>ByteCodeFauxGenerator</span><span>();</span> <span>gen</span><span>.</span><span>execute</span><span>();</span> <span>}</span> <span>public</span> <span>final</span> <span>void</span> <span>execute</span><span>()</span> <span>{</span> <span>comment</span><span>(</span><span>"class"</span><span>);</span> <span>value</span><span>(</span><span>"CLASS"</span><span>);</span> <span>value</span><span>(</span><span>"MODIFIER"</span><span>);</span> <span>value</span><span>(</span><span>"IDENTIFIER"</span><span>);</span> <span>comment</span><span>(</span><span>"statements"</span><span>);</span> <span>value</span><span>(</span><span>"LOCAL_VARIABLE"</span><span>);</span> <span>value</span><span>(</span><span>"RETURN_STATEMENT"</span><span>);</span> <span>}</span> <span>private</span> <span>void</span> <span>comment</span><span>(</span><span>String</span> <span>string</span><span>)</span> <span>{</span> <span>out</span><span>.</span><span>println</span><span>();</span> <span>out</span><span>.</span><span>println</span><span>(</span><span>"// "</span> <span>+</span> <span>string</span><span>);</span> <span>out</span><span>.</span><span>println</span><span>();</span> <span>}</span> <span>private</span> <span>void</span> <span>value</span><span>(</span><span>String</span> <span>string</span><span>)</span> <span>{</span> <span>out</span><span>.</span><span>println</span><span>(</span><span>"static final int "</span> <span>+</span> <span>string</span> <span>+</span> <span>" = "</span> <span>+</span> <span>value</span><span>--</span> <span>+</span> <span>";"</span><span>);</span> <span>}</span> <span>}</span>import static java.lang.System.out; public class ByteCodeFauxGenerator { private int value = -1; public static void main(String[] args) { var gen = new ByteCodeFauxGenerator(); gen.execute(); } public final void execute() { comment("class"); value("CLASS"); value("MODIFIER"); value("IDENTIFIER"); comment("statements"); value("LOCAL_VARIABLE"); value("RETURN_STATEMENT"); } private void comment(String string) { out.println(); out.println("// " + string); out.println(); } private void value(String string) { out.println("static final int " + string + " = " + value-- + ";"); } }
Enter fullscreen mode Exit fullscreen mode
This code resides in the src/test/java
directory of the project. It has a main
method, so I can just run it. It prints:
// classstatic final int CLASS = -1;static final int MODIFIER = -2;static final int IDENTIFIER = -3;// statementsstatic final int LOCAL_VARIABLE = -4;static final int RETURN_STATEMENT = -5;// class static final int CLASS = -1; static final int MODIFIER = -2; static final int IDENTIFIER = -3; // statements static final int LOCAL_VARIABLE = -4; static final int RETURN_STATEMENT = -5;// class static final int CLASS = -1; static final int MODIFIER = -2; static final int IDENTIFIER = -3; // statements static final int LOCAL_VARIABLE = -4; static final int RETURN_STATEMENT = -5;
Enter fullscreen mode Exit fullscreen mode
Then I copy this output and paste it into the actual class, located in src/main/java
:
<span>final</span> <span>class</span> <span>ByteCode</span> <span>{</span><span>// class</span><span>static</span> <span>final</span> <span>int</span> <span>CLASS</span> <span>=</span> <span>-</span><span>1</span><span>;</span><span>static</span> <span>final</span> <span>int</span> <span>MODIFIER</span> <span>=</span> <span>-</span><span>2</span><span>;</span><span>static</span> <span>final</span> <span>int</span> <span>IDENTIFIER</span> <span>=</span> <span>-</span><span>3</span><span>;</span><span>// statements</span><span>static</span> <span>final</span> <span>int</span> <span>LOCAL_VARIABLE</span> <span>=</span> <span>-</span><span>4</span><span>;</span><span>static</span> <span>final</span> <span>int</span> <span>RETURN_STATEMENT</span> <span>=</span> <span>-</span><span>5</span><span>;</span><span>private</span> <span>ByteCode</span><span>()</span> <span>{}</span><span>}</span><span>final</span> <span>class</span> <span>ByteCode</span> <span>{</span> <span>// class</span> <span>static</span> <span>final</span> <span>int</span> <span>CLASS</span> <span>=</span> <span>-</span><span>1</span><span>;</span> <span>static</span> <span>final</span> <span>int</span> <span>MODIFIER</span> <span>=</span> <span>-</span><span>2</span><span>;</span> <span>static</span> <span>final</span> <span>int</span> <span>IDENTIFIER</span> <span>=</span> <span>-</span><span>3</span><span>;</span> <span>// statements</span> <span>static</span> <span>final</span> <span>int</span> <span>LOCAL_VARIABLE</span> <span>=</span> <span>-</span><span>4</span><span>;</span> <span>static</span> <span>final</span> <span>int</span> <span>RETURN_STATEMENT</span> <span>=</span> <span>-</span><span>5</span><span>;</span> <span>private</span> <span>ByteCode</span><span>()</span> <span>{}</span> <span>}</span>final class ByteCode { // class static final int CLASS = -1; static final int MODIFIER = -2; static final int IDENTIFIER = -3; // statements static final int LOCAL_VARIABLE = -4; static final int RETURN_STATEMENT = -5; private ByteCode() {} }
Enter fullscreen mode Exit fullscreen mode
I call it a “faux” code generator because the process is manual. Even though it is manual, it is still effective.
Last week in Objectos Code
And here is a summary of the work I have done in Objectos Code.
Lambda inclusion support
To generate a class with a single field you write the following in Objectos Code:
<span>_class</span><span>(</span><span>id</span><span>(</span><span>"Example"</span><span>),</span><span>field</span><span>(</span><span>_int</span><span>(),</span> <span>id</span><span>(</span><span>"a"</span><span>))</span><span>);</span><span>_class</span><span>(</span> <span>id</span><span>(</span><span>"Example"</span><span>),</span> <span>field</span><span>(</span><span>_int</span><span>(),</span> <span>id</span><span>(</span><span>"a"</span><span>))</span> <span>);</span>_class( id("Example"), field(_int(), id("a")) );
Enter fullscreen mode Exit fullscreen mode
It generates the following:
<span>class</span> <span>Example</span> <span>{</span><span>int</span> <span>a</span><span>;</span><span>}</span><span>class</span> <span>Example</span> <span>{</span> <span>int</span> <span>a</span><span>;</span> <span>}</span>class Example { int a; }
Enter fullscreen mode Exit fullscreen mode
What if you don’t know beforehand the number and names of the fields to be generated?
To this use-case, Objectos Code offers the include
directive:
<span>public</span> <span>class</span> <span>IncludeExample</span> <span>extends</span> <span>JavaTemplate</span> <span>{</span><span>private</span> <span>final</span> <span>List</span><span><</span><span>String</span><span>></span> <span>fieldNames</span> <span>=</span> <span>List</span><span>.</span><span>of</span><span>(</span><span>"a"</span><span>,</span> <span>"b"</span><span>,</span> <span>"c"</span><span>);</span><span>@Override</span><span>protected</span> <span>final</span> <span>void</span> <span>definition</span><span>()</span> <span>{</span><span>_class</span><span>(</span><span>id</span><span>(</span><span>"Example"</span><span>),</span><span>include</span><span>(</span><span>this</span><span>::</span><span>generateFields</span><span>)</span><span>);</span><span>}</span><span>private</span> <span>void</span> <span>generateFields</span><span>()</span> <span>{</span><span>for</span> <span>(</span><span>var</span> <span>fieldName</span> <span>:</span> <span>fieldNames</span><span>)</span> <span>{</span><span>field</span><span>(</span><span>_int</span><span>(),</span> <span>id</span><span>(</span><span>fieldName</span><span>));</span><span>}</span><span>}</span><span>}</span><span>public</span> <span>class</span> <span>IncludeExample</span> <span>extends</span> <span>JavaTemplate</span> <span>{</span> <span>private</span> <span>final</span> <span>List</span><span><</span><span>String</span><span>></span> <span>fieldNames</span> <span>=</span> <span>List</span><span>.</span><span>of</span><span>(</span><span>"a"</span><span>,</span> <span>"b"</span><span>,</span> <span>"c"</span><span>);</span> <span>@Override</span> <span>protected</span> <span>final</span> <span>void</span> <span>definition</span><span>()</span> <span>{</span> <span>_class</span><span>(</span> <span>id</span><span>(</span><span>"Example"</span><span>),</span> <span>include</span><span>(</span><span>this</span><span>::</span><span>generateFields</span><span>)</span> <span>);</span> <span>}</span> <span>private</span> <span>void</span> <span>generateFields</span><span>()</span> <span>{</span> <span>for</span> <span>(</span><span>var</span> <span>fieldName</span> <span>:</span> <span>fieldNames</span><span>)</span> <span>{</span> <span>field</span><span>(</span><span>_int</span><span>(),</span> <span>id</span><span>(</span><span>fieldName</span><span>));</span> <span>}</span> <span>}</span> <span>}</span>public class IncludeExample extends JavaTemplate { private final List<String> fieldNames = List.of("a", "b", "c"); @Override protected final void definition() { _class( id("Example"), include(this::generateFields) ); } private void generateFields() { for (var fieldName : fieldNames) { field(_int(), id(fieldName)); } } }
Enter fullscreen mode Exit fullscreen mode
Which should generate:
<span>class</span> <span>Example</span> <span>{</span><span>int</span> <span>a</span><span>;</span><span>int</span> <span>b</span><span>;</span><span>int</span> <span>c</span><span>;</span><span>}</span><span>class</span> <span>Example</span> <span>{</span> <span>int</span> <span>a</span><span>;</span> <span>int</span> <span>b</span><span>;</span> <span>int</span> <span>c</span><span>;</span> <span>}</span>class Example { int a; int b; int c; }
Enter fullscreen mode Exit fullscreen mode
Remember that Objectos Code is a pure Java template. So the previous example is equivalent to the following string-based template:
class Example {{{#fieldNames}int {{.}};{{/fieldNames}}class Example { {{#fieldNames} int {{.}}; {{/fieldNames} }class Example { {{#fieldNames} int {{.}}; {{/fieldNames} }
Enter fullscreen mode Exit fullscreen mode
Constructor declarations, assignment expressions, and field access expressions
I have started the implementation of constructor declarations. The following Objectos Code:
<span>_class</span><span>(</span><span>id</span><span>(</span><span>"Foo"</span><span>),</span><span>field</span><span>(</span><span>_final</span><span>(),</span> <span>_int</span><span>(),</span> <span>id</span><span>(</span><span>"a"</span><span>)),</span><span>constructor</span><span>(</span><span>param</span><span>(</span><span>_int</span><span>(),</span> <span>id</span><span>(</span><span>"a"</span><span>),</span><span>assign</span><span>(</span><span>n</span><span>(</span><span>_this</span><span>(),</span> <span>"a"</span><span>),</span> <span>n</span><span>(</span><span>"a"</span><span>))</span><span>)</span><span>);</span><span>_class</span><span>(</span> <span>id</span><span>(</span><span>"Foo"</span><span>),</span> <span>field</span><span>(</span><span>_final</span><span>(),</span> <span>_int</span><span>(),</span> <span>id</span><span>(</span><span>"a"</span><span>)),</span> <span>constructor</span><span>(</span> <span>param</span><span>(</span><span>_int</span><span>(),</span> <span>id</span><span>(</span><span>"a"</span><span>),</span> <span>assign</span><span>(</span><span>n</span><span>(</span><span>_this</span><span>(),</span> <span>"a"</span><span>),</span> <span>n</span><span>(</span><span>"a"</span><span>))</span> <span>)</span> <span>);</span>_class( id("Foo"), field(_final(), _int(), id("a")), constructor( param(_int(), id("a"), assign(n(_this(), "a"), n("a")) ) );
Enter fullscreen mode Exit fullscreen mode
Generates the following Java code:
<span>class</span> <span>Foo</span> <span>{</span><span>final</span> <span>int</span> <span>a</span><span>;</span><span>Foo</span><span>(</span><span>int</span> <span>a</span><span>)</span> <span>{</span><span>this</span><span>.</span><span>a</span> <span>=</span> <span>a</span><span>;</span><span>}</span><span>}</span><span>class</span> <span>Foo</span> <span>{</span> <span>final</span> <span>int</span> <span>a</span><span>;</span> <span>Foo</span><span>(</span><span>int</span> <span>a</span><span>)</span> <span>{</span> <span>this</span><span>.</span><span>a</span> <span>=</span> <span>a</span><span>;</span> <span>}</span> <span>}</span>class Foo { final int a; Foo(int a) { this.a = a; } }
Enter fullscreen mode Exit fullscreen mode
More enum declarations
I have also continued the work on enum declarations. Enum class declarations are currently required in Objectos HTML.
The following Objectos Code:
<span>var</span> <span>test</span> <span>=</span> <span>PackageName</span><span>.</span><span>of</span><span>(</span><span>"test"</span><span>);</span><span>var</span> <span>iface</span> <span>=</span> <span>ClassName</span><span>.</span><span>of</span><span>(</span><span>test</span><span>,</span> <span>"Iface"</span><span>);</span><span>_enum</span><span>(</span><span>_public</span><span>(),</span> <span>id</span><span>(</span><span>"Test"</span><span>),</span> <span>_implements</span><span>(</span><span>iface</span><span>),</span><span>enumConstant</span><span>(</span><span>id</span><span>(</span><span>"A"</span><span>),</span> <span>s</span><span>(</span><span>"a"</span><span>)),</span><span>enumConstant</span><span>(</span><span>id</span><span>(</span><span>"B"</span><span>),</span> <span>s</span><span>(</span><span>"b"</span><span>)),</span><span>field</span><span>(</span><span>_private</span><span>(),</span> <span>_final</span><span>(),</span> <span>t</span><span>(</span><span>String</span><span>.</span><span>class</span><span>),</span> <span>id</span><span>(</span><span>"value"</span><span>)),</span><span>constructor</span><span>(</span><span>_private</span><span>(),</span><span>param</span><span>(</span><span>t</span><span>(</span><span>String</span><span>.</span><span>class</span><span>),</span> <span>id</span><span>(</span><span>"value"</span><span>)),</span><span>assign</span><span>(</span><span>n</span><span>(</span><span>_this</span><span>(),</span> <span>"value"</span><span>),</span> <span>n</span><span>(</span><span>"value"</span><span>))</span><span>),</span><span>method</span><span>(</span><span>annotation</span><span>(</span><span>Override</span><span>.</span><span>class</span><span>),</span><span>_public</span><span>(),</span> <span>_final</span><span>(),</span> <span>t</span><span>(</span><span>String</span><span>.</span><span>class</span><span>),</span> <span>id</span><span>(</span><span>"toString"</span><span>),</span><span>_return</span><span>(</span><span>n</span><span>(</span><span>"value"</span><span>))</span><span>)</span><span>);</span><span>var</span> <span>test</span> <span>=</span> <span>PackageName</span><span>.</span><span>of</span><span>(</span><span>"test"</span><span>);</span> <span>var</span> <span>iface</span> <span>=</span> <span>ClassName</span><span>.</span><span>of</span><span>(</span><span>test</span><span>,</span> <span>"Iface"</span><span>);</span> <span>_enum</span><span>(</span> <span>_public</span><span>(),</span> <span>id</span><span>(</span><span>"Test"</span><span>),</span> <span>_implements</span><span>(</span><span>iface</span><span>),</span> <span>enumConstant</span><span>(</span><span>id</span><span>(</span><span>"A"</span><span>),</span> <span>s</span><span>(</span><span>"a"</span><span>)),</span> <span>enumConstant</span><span>(</span><span>id</span><span>(</span><span>"B"</span><span>),</span> <span>s</span><span>(</span><span>"b"</span><span>)),</span> <span>field</span><span>(</span><span>_private</span><span>(),</span> <span>_final</span><span>(),</span> <span>t</span><span>(</span><span>String</span><span>.</span><span>class</span><span>),</span> <span>id</span><span>(</span><span>"value"</span><span>)),</span> <span>constructor</span><span>(</span> <span>_private</span><span>(),</span> <span>param</span><span>(</span><span>t</span><span>(</span><span>String</span><span>.</span><span>class</span><span>),</span> <span>id</span><span>(</span><span>"value"</span><span>)),</span> <span>assign</span><span>(</span><span>n</span><span>(</span><span>_this</span><span>(),</span> <span>"value"</span><span>),</span> <span>n</span><span>(</span><span>"value"</span><span>))</span> <span>),</span> <span>method</span><span>(</span> <span>annotation</span><span>(</span><span>Override</span><span>.</span><span>class</span><span>),</span> <span>_public</span><span>(),</span> <span>_final</span><span>(),</span> <span>t</span><span>(</span><span>String</span><span>.</span><span>class</span><span>),</span> <span>id</span><span>(</span><span>"toString"</span><span>),</span> <span>_return</span><span>(</span><span>n</span><span>(</span><span>"value"</span><span>))</span> <span>)</span> <span>);</span>var test = PackageName.of("test"); var iface = ClassName.of(test, "Iface"); _enum( _public(), id("Test"), _implements(iface), enumConstant(id("A"), s("a")), enumConstant(id("B"), s("b")), field(_private(), _final(), t(String.class), id("value")), constructor( _private(), param(t(String.class), id("value")), assign(n(_this(), "value"), n("value")) ), method( annotation(Override.class), _public(), _final(), t(String.class), id("toString"), _return(n("value")) ) );
Enter fullscreen mode Exit fullscreen mode
Generates:
<span>public</span> <span>enum</span> <span>Test</span> <span>implements</span> <span>test</span><span>.</span><span>Iface</span> <span>{</span><span>A</span><span>(</span><span>"a"</span><span>),</span><span>B</span><span>(</span><span>"b"</span><span>);</span><span>private</span> <span>final</span> <span>java</span><span>.</span><span>lang</span><span>.</span><span>String</span> <span>value</span><span>;</span><span>private</span> <span>Test</span><span>(</span><span>java</span><span>.</span><span>lang</span><span>.</span><span>String</span> <span>value</span><span>)</span> <span>{</span><span>this</span><span>.</span><span>value</span> <span>=</span> <span>value</span><span>;</span><span>}</span><span>@java</span><span>.</span><span>lang</span><span>.</span><span>Override</span><span>public</span> <span>final</span> <span>java</span><span>.</span><span>lang</span><span>.</span><span>String</span> <span>toString</span><span>()</span> <span>{</span><span>return</span> <span>value</span><span>;</span><span>}</span><span>}</span><span>public</span> <span>enum</span> <span>Test</span> <span>implements</span> <span>test</span><span>.</span><span>Iface</span> <span>{</span> <span>A</span><span>(</span><span>"a"</span><span>),</span> <span>B</span><span>(</span><span>"b"</span><span>);</span> <span>private</span> <span>final</span> <span>java</span><span>.</span><span>lang</span><span>.</span><span>String</span> <span>value</span><span>;</span> <span>private</span> <span>Test</span><span>(</span><span>java</span><span>.</span><span>lang</span><span>.</span><span>String</span> <span>value</span><span>)</span> <span>{</span> <span>this</span><span>.</span><span>value</span> <span>=</span> <span>value</span><span>;</span> <span>}</span> <span>@java</span><span>.</span><span>lang</span><span>.</span><span>Override</span> <span>public</span> <span>final</span> <span>java</span><span>.</span><span>lang</span><span>.</span><span>String</span> <span>toString</span><span>()</span> <span>{</span> <span>return</span> <span>value</span><span>;</span> <span>}</span> <span>}</span>public enum Test implements test.Iface { A("a"), B("b"); private final java.lang.String value; private Test(java.lang.String value) { this.value = value; } @java.lang.Override public final java.lang.String toString() { return value; } }
Enter fullscreen mode Exit fullscreen mode
Until the next edition
So that’s it for today. I hope you’ve enjoyed reading.
You can find the source code in this GitHub repository.
Please send me an e-mail if you have comments, questions or corrections regarding this post.
If you liked this content you can follow me on Twitter.
原文链接:LWO #002: Annotations are just modifiers, array access curiosity, faux code generators and more
暂无评论内容