OW #003: A type annotation curiosity, the qualified superclass constructor invocation and more
Tags: java, weeklyretro
Published: 2022-12-01 11:37:12

Hi, welcome to the third issue of Objectos Weekly.

I decided to rename this project. The old name, Last Week in Objectos, is no more. This is now called Objectos Weekly. I will sometime refer it as "OW" for short.

Let's begin.

## Does this an annotation apply to the type or to the declaration?

In the [last issue](https://dev.to/marcioendo/lwo-002-annotations-are-just-modifiers-array-access-curiosity-faux-code-generators-and-more-772), I wrote that, syntactically speaking, [annotations are just modifiers](https://dev.to/marcioendo/lwo-002-annotations-are-just-modifiers-array-access-curiosity-faux-code-generators-and-more-772#annotations-are-just-modifiers-grammatically-speaking).

While the example focused on method declarations, the same principle applies to all declarations where annotations are allowed. For example, the following is valid Java code:

```java
public class TypeAnnotationsExample {

  @Target(ElementType.FIELD)
  @Retention(RetentionPolicy.RUNTIME)
  @interface F {}

  @Target(ElementType.TYPE_USE)
  @Retention(RetentionPolicy.RUNTIME)
  @interface U {}

  @Target({ElementType.FIELD, ElementType.TYPE_USE})
  @Retention(RetentionPolicy.RUNTIME)
  @interface X {}

  private @U volatile @F transient @X int a;

}
```

Remember that annotations can go on declarations such as a class, a method or a field declaration. And, since Java 8, you can also annotate the [types themselves](https://docs.oracle.com/javase/tutorial/java/annotations/type_annotations.html).

So, in the example above, annotations might be annotating:

- the field declaration; and/or
- the type of the field, i.e., the `int` type.

But how can we know which annotation is being applied to what?

The answer lies in the `@Target` meta information of each of the annotations:

- annotation `@F` applies to the field as its `@Target` is defined as `FIELD` only;
- annotation `@U` applies to the `int` type as its `@Target` is defined as `TYPE_USE` only; and
- annotation `@X` applies to both the field and the `int` type as its `@Target` is defined as both `FIELD` and `TYPE_USE`.

To confirm we write a small program:

```java
public static void main(String[] args) throws NoSuchFieldException, SecurityException {
  var exampleClass = TypeAnnotationsExample.class;

  var field = exampleClass.getDeclaredField("a");

  var fieldAnnotations = field.getDeclaredAnnotations();

  System.out.println("Field annotations are:");

  printAnnotations(fieldAnnotations);

  var annotatedType = field.getAnnotatedType();

  System.out.println("Type annotations are:");

  printAnnotations(annotatedType.getDeclaredAnnotations());
}

private static void printAnnotations(Annotation[] annotations) {
  for (var annotation : annotations) {
    System.out.println(annotation);
  }
}
```

And when we run it, it prints:

```
Field annotations are:
@post.TypeAnnotationsExample.F()
@post.TypeAnnotationsExample.X()
Type annotations are:
@post.TypeAnnotationsExample.U()
@post.TypeAnnotationsExample.X()
```

## The qualified superclass constructor invocation

An inner class instance _must_ be associated to an instance of its enclosing class. In other words, to create an instance of an inner class, we must first create an instance of the outer class.

To illustrate the previous paragraph, consider the following [jshell](https://docs.oracle.com/en/java/javase/19/jshell/introduction-jshell.html) session.

First, we create the `Inner` class nested in the `Outer` class:

```
jshell> class Outer {
   ...>     class Inner {}
   ...> }
|  created class Outer
``` 

Let's try to create an `Inner` instance as if it were a static nested class:

```
jshell> var inner = new Outer.Inner();
|  Error:
|  an enclosing instance that contains Outer.Inner is required
|  var inner = new Outer.Inner();
|              ^---------------^
```

We can't. We must first create an instance of the outer class:

```
jshell> var outer = new Outer();
outer ==> Outer@3941a79c

jshell> var inner = outer.new Inner();
inner ==> Outer$Inner@4fca772d
```

We could have also written it in a _one-liner_:

```
jshell> var inner = new Outer().new Inner();
inner ==> Outer$Inner@b1bc7ed
```

The takeaway here is:

- in order to have an instance of the `Inner` we must provide an instance of the `Outer`. 

### What if we subclass the `Inner` class?

If we create a subclass of the `Inner` class the previous requirement must still hold true. In other words, if we create a subclass `InnerChild` like so:

```java
class InnerChild extends Outer.Inner {}
```

We must somehow provide an instance of `Outer` to `InnerChild`. And things get a little more complicated if we need to invoke a specific `Inner` constructor from `InnerChild`.

Let's start a new [jshell](https://docs.oracle.com/en/java/javase/19/jshell/introduction-jshell.html) session. Next, let's write a new version of `Outer` and `Inner`:

```
jshell> class Outer {
   ...>     Outer() { System.out.println("Outer()"); }
   ...>     Outer(boolean ignore) { System.out.println("Outer(bool)"); }
   ...>     
   ...>     class Inner {
   ...>         Inner() { System.out.println("Inner()"); }
   ...>         Inner(boolean ignore) { System.out.println("Inner(bool)"); }
   ...>     }
   ...> }
|  created class Outer
```

Next, we define the `InnerChild` as a subclass of `Inner`:

```
jshell> class InnerChild extends Outer.Inner {
   ...>     InnerChild() {
   ...>         new Outer().super();
   ...> 
   ...>         System.out.println("InnerChild()");
   ...>     }
   ...> 
   ...>     InnerChild(Outer outer) {
   ...>         outer.super(true);
   ...> 
   ...>         System.out.println("InnerChild(Outer)");
   ...>     }
   ...> }
|  created class InnerChild
```

As mentioned, we must, somehow, provide an instance of `Outer` to `InnerChild`. The first statement in the first constructor does exactly that:

```java
new Outer().super();
```

It explicitly create an `Outer` instance and immediately invokes the `Inner` constructor that takes no arguments.

In the second constructor, the `Outer` instance is passed as a parameter:

```java
InnerChild(Outer outer) {
  outer.super(true);
  
  ...
}
```

And from the `Outer` instance, it invokes the `Inner` constructor that takes the boolean argument.

These two `super` statements are examples of __qualified superclass constructor invocation__.

Let's see them in action. First, we create an `InnerChild` with no arguments:

```
jshell> new InnerChild();
Outer()
Inner()
InnerChild()
$7 ==> InnerChild@7cd84586
```

Let's now create an `InnerChild` with the `Outer` argument. First we create an `Outer` instance:

```
jshell> var outer = new Outer(true);
Outer(bool)
outer ==> Outer@30dae81
```

Then we create the `InnerChild` instance:

```
jshell> new InnerChild(outer);
Inner(bool)
InnerChild(Outer)
$9 ==> InnerChild@4edde6e5
```

I have never used them in "real-life" code. And, in fact, I have just learned about them. So I thought it would be interesting to share.

## Objectos Code Weekly

Work on Objectos Code is still in progress. Here are a few examples of what is already possible.

### Simple `Box` type

You can already write simple classes. The following Objectos Code:

```java
public class BoxObjectosCodeExample extends JavaTemplate {
  public @interface TypeAnnotation {}

  @Override
  protected final void definition() {
    _package("com.example");

    autoImports();

    _class(
      annotation(TypeAnnotation.class),
      _public(), id("Box"),

      field(
        _private(), _final(), _int(), id("value")
      ),

      constructor(
        _public(),
        param(_int(), id("value")),
        assign(n(_this(), "value"), n("value"))
      ),

      method(
        _public(), _final(), _int(), id("get"),
        _return(n("value"))
      )
    );
  }
}
```

Generates:


```java
package com.example;

import post.BoxObjectosCodeExample.TypeAnnotation;

@TypeAnnotation
public class Box {
  private final int value;

  public Box(int value) {
    this.value = value;
  }

  public final int get() {
    return value;
  }
}
```

### Nested classes

You can also have nested classes:

```java
public class NestedClassObjectosCodeExample extends JavaTemplate {
  @Override
  protected final void definition() {
    _package("com.example");

    autoImports();

    _class(
      _public(), id("Outer"),

      _class(
        id("Inner")
      )
    );
  }
}
```

Generates:

```java
package com.example;

public class Outer {
  class Inner {}
}
```

### Chained methods

You can already declare chained method invocations:

```java
public class ChainedMethodsExample extends JavaTemplate {
  class User {}

  @Override
  protected final void definition() {
    _package("com.example");

    autoImports();

    _class(
      _public(), id("ChainedMethods"),

      method(
        _public(), _static(), _void(), id("main"),
        param(t(t(String.class), dim()), id("args")),

        var("user", chain(
          invoke(t(User.class), "builder"), nl(),
          invoke("id", i(123)), nl(),
          invoke("login", s("foo")), nl(),
          invoke("build")
        )),

        invoke(n(ClassName.of(System.class), "out"), "println", n("user"))
      )
    );
  }
}
```

Generates:

```java
package com.example;

import post.ChainedMethodsExample.User;

public class ChainedMethods {
  public static void main(String[] args) {
    var user = User.builder()
        .id(123)
        .login("foo")
        .build();
    System.out.println(user);
  }
}
```

## Until the next issue of Objectos Weekly

So that's it for today. I hope you've enjoyed reading.

You can subscribe to this blog via [RSS](https://www.objectos.com.br/atom.xml). You can also follow me on [Twitter](https://twitter.com/marcioendo).

The source code of all of the examples are in this [GitHub repository](https://github.com/objectos/blog-examples/tree/master/p023-ow-003/src/main/java/post).