3 Asinine Things About Java

Alexander Floyd
5 min readJun 15, 2022
Photo by Ryan Snaadt on Unsplash

Java is one of the most popular programming languages in the world, especially for big businesses. It wouldn’t be a stretch to say that Java runs a significant portion of the web today, more so from older, less techy companies. Java is a tried and true, stable language with a huge ecosystem and incredible portability. All of that said, I hate Java, and I’m going to tell you just a few of my biggest gripes with the language.

Boilerplate, Boilerplate, Boilerplate

Everything in Java is too verbose and nothing can be done without a few too many keywords.

Public, private, protected, static, volatile, abstract, interface, implements, extends…

Let’s consider the simple example of a data class that holds the first and last names of a person. We have to declare the class with a public header if we actually want to use it anywhere, declare the private class variables, create one or more constructors, and add in the getters and setters!

public class Person {
private String firstName;
private String lastName;
public Person(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public Person(String firstName) {
this.firstName = firstName;
this.lastName = null;
}
public String getFirstName() {
return this.firstName;
}
public String getLastName() {
return this.lastName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}

And that’s it! That’s a 24 line class to represent our person with only a first and last name. Here’s an identical, 4 line class in Python:

class Person:
def __init__(self, firstName, lastName=None):
self.firstName = firstName
self.lastName = lastName

Does a simple data class like this really need to be so long in Java? Probably not, but there’s a reason Java is like this: it’s idiot-proofed. Everything needs to be explicit in Java because anything else could lead to disaster (or that’s the idea). Languages like Python and JavaScript are completely dynamically typed, C++ is static with some caveats, but Java is soul-crushingly statically typed. Don’t expect to do anything in just a few lines, and get used to class definitions that look like this:

public Class ArrayList<E> implements Serializeable, Clonable, Iterable<E>, Collection<E>, List<E>, RandomAccess

No First-Class Functions

First-class functions are a fundamental feature of most widely used programming languages, but not Java. While they may not be as important as the other things on this list, the lack of first-class functions is a huge personal gripe of mine. First-class functions allow us to use functions the same way as any other variable by assigning a reference to it. Here’s a basic example using Python:

def add_two_numbers(a, b):
return a + b
function_ptr = add_two_numbers
print(function_ptr(1, 2))
>>> 3

Using first-class functions allows one to assign a function to a variable and call it. This example may not make it seem like an especially useful functionality, but consider callbacks in JavaScript. It’s not that similar functionality is impossible in Java, but it suffers from the Java object-oriented, boilerplate bloat that everything else does. Here’s how you could create a rudimentary generic “function pointer” in Java:

public int hello() {
System.out.println("Hello");
}
public interface IFunctionPtr {
void callFunction();
}
public class HelloFunctionPtr implements IFunctionPtr {
void callFunction() {
hello();
}
}
public static void main(String[] args) {
IFunctionPtr ptr = new HelloFunctionPtr();
ptr.callFunction();
}
>>> Hello

So, yes, it is possible to emulate the functionality of first-class functions in Java. The above example is very simplistic, just imagine how this program would change if you wanted to add a generic way of passing arguments and returning results. Needing to implement an entire class based on a function pointer interface for each function you want to pass around is about as Java as it gets. You could argue this comparison is unfair because Java is a statically typed language while Python and JavaScript are dynamically typed. My response to that is first-class functions in C:

#include "stdio.h"void add(int a, int b) {
return a + b;
}
void main() {
int (*addPtr)(int, int); // Creates function pointer that takes two integer arguments and returns an int.
addPtr = &add; // Assigns the pointer to the address of add
int c = (*addPtr)(1,2); // Calls the function at the pointer
printf("%d", c);
return 0;
}
>>> 3

Sure, function pointers in C (and C++) are more verbose than in JavaScript or Python, but there’s still much less boilerplate than in Java.

Annotations and Metaprogramming

Over-use of annotations is probably what I hate the most about Java. A good example of annotations in Java is Lombok. Consider the above Person class example, here's what can be done with the Lombok @Data annotation:

import lombok.Data;@Data
public class Person {
private String firstName;
private String lastName;
}

This wonderful annotation essentially turns this class into the same 24 line class from the previous example! Lombok is great, and fixes the verbosity problem, right? Yeah, it really does and it makes using Java much less mind-numbing. Lombok inserts itself between the compiler and your code and generates the code that’s missing in this example.

Now that you’re familiar with the @Data annotation from Lombok, let’s look at an example rest controller with a few annotations from Spring Boot and Lombok:

@Data
public class Person {
@JsonProperty("firstName")
private String firstName;
@JsonProperty("lastName")
private String lastName;
}
@Controller
@RequestMapping("people")
public class PersonRestController {
@Autowired
List<Person> people;
@RequestMapping(value = "/add", method = {RequestMethod.POST})
public void addPerson(@PathVariable("firstName") String firstName, @PathVariable("lastName") String lastName) {
Person p = new Person(firstName, lastName);
this.people.add(person);
}
}

This class acts as a rest endpoint that accepts the first and last name of a person and stores them in a list of Person objects. This class is extremely short for what it does, especially compared to the monstrosity this would be without these annotations. I can’t deny that this is better than the alternative, but should a programmer have to use so many annotations to make a somewhat basic program? This may be best practice, but is it the best solution? In my opinion, annotations are a slippery slope. It starts with an @Data class, then your program is 50% annotations and 50% your code (that’s my experience at least).

Annotations are a sacrifice of readability, clarity, transparency, and the explicitness that Java strives for. I work with Java every day on my job, and I’ve formed a love-hate relationship with annotations. Sure, it would take twice as long to write any code without them, but I spend a lot of time trying to figure out esoteric bits of code due to deprecated or sparsely-documented annotations.

I hate Java, and I don’t like to work in its ecosystem. That’s my opinion and I’m sticking to it. That said, I’d love to hear your opinions on Java (and especially on other JVM languages).

--

--

Alexander Floyd

Full-time software engineer, part-time gamer, and a programming language enthusiast.