Even though I’ve been programming in Java for a few years, there are still cases when its syntax surprises me. Let me share a few examples that I thought would not compile when I first saw them, but they did.

Array types

How to declare a variable containing an array of unboxed integers? I’d go with:

int[] intArray;

However, being a C language descendant, Java also allows adding [] to the identifier:

int intArray[];

It doesn’t look weird until both ways are mixed so that:

int[] arrayOfIntArrays[]; 

can be used instead of:

int[][] arrayOfIntArrays; 

There’s even one case when it makes the code shorter, though I hope that nobody uses it this way:

int[] intArray, arrayOfIntArrays[];

has the same meaning as:

int[] intArray;
int[][] arrayOfIntArrays;

Similar syntax can be used to specify a return type of a function. Square brackets can be added to the end of function signature, so that:

int[] fun()[];

is equivalent to:

int[][] fun();

To take it to the extreme, this one also compiles:

int[] fun(int[] arrayOfIntArrays[])[];

It is a method that takes an array of integer arrays and returns an array of integer arrays.

Receiver parameter

This code compiles since Java 8:

class MyClass {
    public void method(MyClass this, int argument) {
    }
}

and generates the same bytecode as:

class MyClass {
    public void method(int argument) {
    }
}

It reminds me Python, where the first argument of class methods is an instance of that class. It is conventionally named self:

class MyClass:
   def method(self, arg):
      print(arg)

There was even a proposal to remove the need to use self as the first argument in Python methods (which would make the syntax more Java-like), but the Benevolent Dictator For Life, Guido van Rossum, didn’t like it. It looks like Java 8 brought a bit of Pythonic self to the Java world instead.

In Java, this also needs to be the first parameter of the method and its type needs to match the type of containing class. The syntax is called the receiver parameter. When can it be useful? According to StackOverflow thread, currently the only use of this syntax is to annotate the argument:

class MyClass {
    public void method(@MyTypeAnnotation MyClass this, int argument) {
    }
}

@Target(ElementType.TYPE_USE)
@interface MyTypeAnnotation {}

The annotation can be then retrieved using reflection. For the same reason, receiver parameter can be added to a non-static inner class constructor, as it is implicitly bound to an instance of the outer class:

class Outer {
    class Inner  {
        public Inner(Outer Outer.this){
        }
    }
}

Receiver parameter syntax was also considered to be used in Project Valhalla, you can read more about it on blog.joda.org.

Array initialization

I used this syntax to initialize an array:

int[] intArray = new int[]{1, 2, 3};

until I found out that I don’t have to specify the type of the array two times and I can just write:

int[] intArray = {1, 2, 3};

Unfortunately I was quickly disappointed that this syntax sugar only works when array initialization immediately follows array declaration. Otherwise it doesn’t compile

int[] intArray;
//intArray = {1, 2, 3}; -> Array initializer is not allowed here 
intArray = new int[]{1, 2, 3}; // longer form has to be used

According to StackOverflow [1, 2], the reason of not allowing “short” array initializers in other places may be the fact that it would make the language grammar harder to parse, but I wasn’t able to find any official explanation.

Bonus: is Lombok still Java?

Lombok is a library that, when added to classpath, acts as an annotation processor and uses internal compiler APIs to modify/generate the source code of annotated classes during compilation. Code snippets in this section were compiled with Lombok version 1.16.12.

Simple usage of Lombok looks like this:

@Value
class MyClass{
    String name;
}

Lombok will see the @Value annotation and make all fields private and final, generate getters for them, generate a constructor and override hashCode, equals and toString methods appropriately. It’s quite useful, as they are automatically updated if another field is added.

Knowing that Lombok is an annotation processor one can expect having additional annotations here and there. However, in addition to that Lombok brings some unexpected syntaxes like this one:

@AllArgsConstructor(onConstructor = @__(@Autowired(required=true)))
class MyClass {
    private final MyOtherClass dependency;
}

The code uses @AllArgsConstructor which tells Lombok to generate a constructor that takes initial values for all the fields in the class as arguments. The problem is that sometimes the programmer wants to add an annotation to the constructor generated by Lombok – that’s what onConstructor annotation element is for. Unfortunately, it looks like in Java 7 there was no elegant way to support this use case, so Lombok developers decided to use a non-existent @__ annotation and remove it when processing annotations. Lombok documentation and this StackOverflow answer provide more details.

Strange annotations are still only annotations, but Lombok made me a big surprise once I accidentally pasted Scala code into a .java file and noticed there were no compilation errors. That’s how I discovered that Lombok can create immutable values with automatically inferred types:

public double calculate() {
    val a = 5;
    val b = 10.5;
    return a + b;
}

As documentation explains, val is a real type and has to be imported as import lombok.val;. Lombok changes it to the actual inferred type and adds the final keyword in front of it.

So, is Lombok still Java? Lombok’s readme on GitHub seems to explain it

Project Lombok makes java a spicier language by adding ‘handlers’ that know how to build and compile simple, boilerplate-free, not-quite-java code.


Comments on r/java