It Ain't Your Grandpappy's Java...

Modern Java is... nice? When did that happen?

Recent Java releases bring a lot of QoL improvements.

Here are a few of the biggest...

Java is the de facto instructional language of many universities. It's widespread, it runs on most platforms, it makes a good case study in OOP concepts, and there are a lot of teachers available.

But in many cases, the Java that's taught in the classroom isn't much like production Java. We learn the oldest syntax, and the oldest design patterns, that accomplish the task. It makes typing Java feel like drudgery compared to a more modern language like Rust or Go. Seriously, who wants to type this mess:

MySpecialClassName myClass = new MySpecialClassName();

to instantiate a variable?

The var Keyword

In more modern languages, we have type inference. The compiler can tell what a type a variable holds based on what's assigned to it. But wait, Java actually has this too! Instead we can write this:

var myClass = new MySpecialClassName();

which is much more streamlined. var is a special "reserved type name" that was added in Java 10, to make declarations easier to write. So why don't we learn this in university? Personally, the Java courses I've taken have been Java 7 compatible, or older. Java 7 was released in 2011. A lot has changed since then.

The Optional Type

In Rust, there's a special enum included in the compiler's prelude, called Option. It has two variants, Some() and None. The convention is to use it when a function may or may not return something, such as a query to a database.

Java added a similar concept with the Optional<?> in Java 8 (released in 2014). It's a box that might hold a value, or a null pointer. The biggest advantage is that by making this return type explicit, developers have to handle the possibility of a null pointer when it might be returned from a method. Null-checking is simplified. This:

Apple apple = mightBeNull("granny smith");

if (apple != null) {
    System.out.println(apple.toString());
} else {
    System.out.println("apple was null");
}

becomes this (if we use our fancy new type inference):

Optional<Apple> optApple = mightBeNull("granny smith");

var appleVariety = optApple.orElse("No apple in this box...");

System.out.println(appleVariety); // This is safe now!

Record Classes

A common pattern in Java is using an object to hold related data, usually as it's being moved from a source to a consumer. If you had a database of apples, you might represent each apple as a class, like this:

public class Apple {
    private String variety;
    private float pricePerPound;
    
    public String getVariety() {
        return this.variety;
    }
    
    public float getPrice() {
        return this.pricePerPound;
    }
    
    public Apple(String v, float p) {
        this.variety = v;
        this.pricePerPound = p;
    }
    
    @Override
    public String toString() {
        return "Apple(variety=" + this.getVariety() + ", price=" + this.getPrice();
    }
}

That's a lot of code for one apple! Java 14 added a solution in the form of the record class. With modern Java, our Apple is just:

public record AppleRecord(String variety, float pricePerPound) {}

That's literally it.

It implements getters automatically; just call AppleRecord.variety() to get the variety, for example. By default, the fields are immutable, so a record is instantiated like this:

var apple = new AppleRecord("pink lady", 0.20);

If you need custom logic, you can override these default methods in the record's block. Easy!

Conclusion

So why aren't we being taught these concepts? Is it the result of a one-size-fits-all approach to CS education? Are the instructors even familiar with these later developments in the Java ecosystem? I don't know.

What I do know is that being able to think in terms of Optionals, and reduce boilerplate code, will make Java feel like a whole new language for me!