Records in Java (JEP 359, preview)

Records in Java look very promising to me and a great addition to the language. The ceremony of creating pure data holder classes will be well know to any Java developer.

Sometimes we just create a class to transport some data from A to B. Most of the times we don’t even care about object equality or an efficient hash code algorithm. Nonetheless, the amount of code you (usually) generate is quite a bit. I’d go so far to say that the need to create classes for everything sometimes takes me out of the flow.

Take this simple example:

public class Person {
  private String name;
  private String firstname;
  private String address;
 
  public Person(String name, String firstname, String address) {
    this.name = name;
    this.firstname = firstname;
    this.address = address;
  }

  public String getName() {
    return this.name;
  }
  
  public void setName(String name) {
    this.name = name;
  }

  // ... all the other getters and setters, hashCode() and equals(), toString()

With records we would be able to declare a pure data holder structure way easier. And the best thing: it takes care about equality, hash code generation and a proper string representation (toString())

record Person(String name, String firstname, String address) {};
Image result for meme unbelievable

Yep, that one line expresses the same thing as the class above.

As a seasoned Java developer you may know that you can declare a class locally as part of a method. I don’t think this is common practice, but with records I could imagine that we can solve several problems in a very elegant way by just declaring a local record.

Try it out today

You can download early access builds from https://jdk.java.net/14/ (just unzip it somewhere you find it again). No comfort version, without any IDE – it’s fun to use these commands from time to time. Just keep in mind to enable the preview features:

Compile

c:\Dev\jdk-14\bin\javac -source 14 –enable-preview YourClass.java

Run

c:\Dev\jdk-14\bin\java –enable-preview YourClass

Personal opinion

I like it. But I feel like I’m saying this for every new Java feature. I do have some concerns about pattern matching and switch expressions as you can read in my other posts. But I don’t see a lot of trouble with this one coming!

Switch Expressions in Java (JEP 361)

With Java 14 we will get a new feature that simplifies the switch statement. It will provide a new and clearer way to write switch statements and in addition allows us to use switch as an expression yielding a value.

New Syntax

Forget about break! No fall through anymore – simple and concise.

switch (day) {
    case MONDAY             -> System.out.println("Fully motivated!");
    case TUESDAY, WEDNESDAY -> System.ouFt.println("Get this done!");
    case THURSDAY, FRIDAY   -> System.out.println("Almost done!");
    case SATURDAY, SUNDAY   -> System.out.println("Party time!");
}

Today you would write something like below. Don’t miss the breaks!

switch (day) {
   case MONDAY:
       System.out.println("Fully motivated!");
       break;
   case TUESDAY:
   case WEDNESDAY: 
        System.ouFt.println("Let's get this done!");
        break;
   case THURSDAY:
   case FRIDAY:   
       System.out.println("Almost done!");
       break;
   case SATURDAY:
   case SUNDAY:
       System.out.println("Party time!");
}

Switch Expressions

This is really cool. Now we can asisgn the result of a switch expression to a variable.

String workingDay = switch(day) {
    case 1,2,3,4,5 -> "yes";
    case 6,7 -> "no";
    default -> "don't know";
};

This is easy to read and allows us to simplify our code. Maybe until now you used nested conditional operators (!!) or you introduced a little helper method with return statements.

If you need an actual block to calculate the result of the expression, there is a new keyword you can use for that purpose: yield

String workingDay = switch(day) {
    case 1,2,3,4,5 -> "yes";
    case 6,7 -> "no";
    default -> {
       String defaultAnswer = calculateDefaultAnswer();
       yield defaultAnswer;
    }
};

You can also use the legacy switch syntax and form expressions using the yield keyword.

int result = switch (s) {
    case "Foo": 
        yield 1;
    case "Bar":
        yield 2;
    default:
        System.out.println("Neither Foo nor Bar, hmmm...");
        yield 0;
};

It’s an expression baby

Image result for coding meme

Yes, you can drive your co worker crazy by building complex and inlined switch expressions. It works – I tried it.

public static boolean isWorkingDay(String day) {        
    if ("yes".equals(switch (day) { case "Monday", "Tuesday", "Wednesday", "Thursday", "Friday" -> "yes"; case "Saturday", "Sunday" -> "no"; default -> "dont' know";})) {
        return true;
    } else {
        return false;
    }
}

Try it out today

You can download early access builds from https://jdk.java.net/14/ (just unzip it somewhere you find it again). With Java 14 this is not a preview feature anymore, so you can just start to use the new switch expressions.

Personal opinion

In short: I really like it. I think it makes a lot of sense. Having the privilege to also teach classes in programming I can say that the intention of the programmer when using the switch statement was always a different one – always.

In addition using switch as an expression provides new ways also for a seasoned programmer to simplify their code. Have you ever seen those nested tenary conditional operators?

One downside I see is developers thinking that it is cool to inline switch expressions and combine them to more complex expressions that no one will ever touch again.

Image result for i can do it meme

Pattern Matching for instanceof (JEP 305)

Finally with Java 14 we get a (preview) feature I had on my wishlist for a long time. It eliminates the need to first test an object via instanceof operator and then (and I asusme it is the 90% case) cast it to exact that class in order to do something with it.

Here is the example directly taken from the JEP site:

if (obj instanceof String s) {
    // can use s here
} else {
    // can't use s here
}

Before we we had to write something like:

if (obj instanceof String) {
    String s = (String) obj;
} else {
    
}

But it gets even better

The binding variable that is introduced by the instanceof operator is not only accessible in the actual true block, but also in the logical extension of the boolean expression. I don’t know how to describe it in a better way.

if (obj instanceof String s && s.contains("hello")) {
  System.out.println("It contains the magic word!");
}

On the other hand this will not work and if you think it through a bit it also makes sense.

if (obj instanceof String s || s.contains("hello")) { // won't work!
  System.out.println("It contains the magic word!");
}

Try it out today

You can download early access builds from https://jdk.java.net/14/ (just unzip it somewhere you find it again). No comfort version, without any IDE – it’s fun to use these commands from time to time.

Code

package ch.christianmenz.java14;

public class PatternMatching {
    public static void main(String[] args) {
        Object obj = "hello world";
        if (obj instanceof String s) {
            System.out.println(s.length());
          }
    }
}

Compilation

C:\Users\chris\Documents\Java14\src>c:\Dev\jdk-14\bin\javac -d . -source 14 –enable-preview ch\christianmenz\java14\PatternMatching.java

It is important that you pass the source and the –enable-preview parameters.

Running

Running is also quite simple (note you don’t have to use pacakges as I did, I just did it for the nostalgic feeling).

C:\Users\chris\Documents\Java14\src>c:\Dev\jdk-14\bin\java –enable-preview -cp . ch.christianmenz.java14.PatternMatching

Extra: without manual compilation

If you read about this Java 11 feature, you might wonder if you could also use these preview features: yes you can! Just note you have to pass a double dash this time for the source parameter (I guess because of reasons ;-)).

C:\Users\chris\Documents\Java14\src>c:\Dev\jdk-14\bin\java –enable-preview –source 14 ch\christianmenz\java14\PatternMatching.java

Personal opinion

I’m a bit ambivalent about this feature. I certainly like that some boilerplate code can be eliminated. On the other hand the use of this language construct in combination with more complex expressions might lead to more misunderstandings and harder to understand software. Also keep an eye on this draft JEP, which aims to extend pattern matching to the switch statement: https://openjdk.java.net/jeps/8213076