Do you want your ad here?

Contact us to get your ad seen by thousands of users every day!

[email protected]

Increase readability and reduce complexity with Java’s Pattern Matching

  • March 14, 2024
  • 5291 Unique Views
  • 3 min read
Table of Contents
The usage of instanceOfPattern MatchingPattern matching in switch casesSwitch expressionsConclusions

Increase readability, reduce cognitive complexity, and avoid bugs that are hard to spot with Java's Pattern Matching.

I bet you don’t like writing ugly but necessary boilerplate code or reading it. But, sometimes we need to create logic that has to deal with an object of unknown type and follow different paths depending on the type. This code is prone to be too verbose, is complex to understand, and may involve some hidden errors hard to spot due to intermediate assignments.

In this article, I will show different ways of checking the type of an object and keeping the code easy to understand while also reducing the chances of introducing bugs hard to spot.

The usage of instanceOf

In Java, we’ve been using instanceOf conditional statements, type casting, and temporary assignments for that purpose.

public String processElement(Object element) {
  String result;

  if (element instanceOf String) { 
    String elementStr = (String) element;
    result = elementStr;
  } else if (element instanceOf Person) {
    Person elementPerson = (Person) element;
    result = elementPerson.getName();
  }

  return result + " value";
}

This involves a lot of boilerplate code which is not very readable. But even more important, it allows coding errors to remain hidden. In this structure, nothing is ensuring we are assigning a value to the intermediate variable result and that could mean having an empty value at the end.

But Java has included new features since version 14 that will help us to improve in this area. Let’s discover them.

Pattern Matching

In Java 16 an improvement was added in order to reduce code repetition and boilerplate: Pattern Matching for instanceOf cases. With this approach, the cast is included in the condition which is easier to read, reducing the boilerplate code.

public String processElement(Object element) {
  String result;

  if (element instanceOf String s) { 
   result = s;
  }

  if (element instanceOf Person elementPerson) {
    result = elementPerson.getName();
  }

  return result + " value";
}

With this change, we avoid the need for an extra type-cast, that is making the code harder to read, and even can involve more errors.

Yes, I agree with you, this is not solving the problem entirely. We have improved but we are not there yet. Let’s see if Java provides more tricks ...

Pattern matching in switch cases

In order to improve the readability a bit and reduce complexity we can use a switch/case statement. With this approach, we get rid of the “else if” clauses, making it clear that cases are exclusive and have different branches.

public String processElement(Object element) {
  String result;

  switch (element) {
   case (String s): 
     result = s;
     break;
   case (Person elementPerson):
    result = elementPerson.getName();
    break;
  }

  return result + " value";
}

But this code is still hard to read, I know. And it’s still weak in terms of errors that can happen by missing one break or by not assigning the value to the intermediate variable.

Switch expressions

In order to fix this situation we can use a very interesting feature included in Java 14: switch expressions. We will reduce the code even more, increase the readability and clarity, and avoid the bugs caused by missing intermediate assignments.

Also, we reduce the cognitive complexity of the resulting code by half and this positively impacts the readability and maintainability of the code. We need to keep in mind that too high complexity is one of the most common issues detected by Sonar tools in all the thousands of projects analyzed.

return switch (obj) {
    case Person person-> String.format("Person %s", person.getName());
    case String s -> String.format("Str %s", s);
    default -> obj.toString();
  } + " value";

With this approach, we have a very clear idea of what the code is doing and also reduce the risk of errors.

If you want to calculate the cognitive complexity of your code, you can use the "Code complexity" plugin (in IntelliJ) that will give you a hint of your method’s complexity.

private void getStringsUsingInstanceOfIfs(Object user) { @ simple(25%)
    ...
}

private void getStringsUsingSwitchExpressionPattern(Object user) { @ simple(0%)
    ...
}

The Sonar Java analyzer will warn you if your code has too high complexity, and also will suggest using the switch pattern matching approach and the switch expression in order to improve readability.

Conclusions

We spend way more time reading code than writing it, so it’s super important to make our code conventional and intentional in order to help us understand its purpose.

The Java language adds new features in every release to help you write consistent, simple, and robust code providing standardized ways of solving common issues and reducing the time to understand the purpose of the code and the probability of errors.

Sponsored Content

Declutter Your Code: Your Undead Code Is A Time Vampire

The average Java application contains somewhere between 10 to 50% dead code. In this webinar we'll discuss ways of monitoring JVMs across different environments to identify what runs or doesn't run in each, identify what you can get rid of, and how to work better on these larger applications.

Sign Up Here

Do you want your ad here?

Contact us to get your ad seen by thousands of users every day!

[email protected]

Comments (5)

Highlight your code snippets using [code lang="language name"] shortcode. Just insert your code between opening and closing tag: [code lang="java"] code [/code]. Or specify another language.

Harald avatar

Harald

10 months ago

I am looking forward to using such patterns, but it is blatantly obvious from the example how sorely Java is missing the possibility to create arbitrary union types. The method signature should be [code lang="java"] public String processElement(String | Person element) { [/code] for best readability. Seeing Object as the parameter type in production code would make me extremely nervous.

Highlight your code snippets using [code lang="language name"] shortcode. Just insert your code between opening and closing tag: [code lang="java"] code [/code]. Or specify another language.

Jonathan Vila avatar

Jonathan Vila

10 months ago

@Harald Thanks a lot for your comment. I agree that having union types would have made the method signature clearer. The example is an oversimplification, but in real life, you could use a common parent in the signature, or use sealed classes (https://spin.atomicobject.com/java-sealed-interface/) In any case that would not change the use of the pattern matching. But I totally support the union types as a way to define the list of possible types.

Highlight your code snippets using [code lang="language name"] shortcode. Just insert your code between opening and closing tag: [code lang="java"] code [/code]. Or specify another language.

Java Weekly, Issue 534 – All About Java 22 | Baeldung

10 months ago

[…] >> Increase readability and reduce complexity with Java’s Pattern Matching [foojay.io] […]

Highlight your code snippets using [code lang="language name"] shortcode. Just insert your code between opening and closing tag: [code lang="java"] code [/code]. Or specify another language.

Raghav avatar

Raghav

10 months ago

Really a great article the way it explained about pattern matching and switch expressions. Really Helpful and informative

Highlight your code snippets using [code lang="language name"] shortcode. Just insert your code between opening and closing tag: [code lang="java"] code [/code]. Or specify another language.

Java Annotated Month-to-month – April 2024

10 months ago

[…] Improve readability and cut back complexity with Java’s Sample Matching – Jonathan Vila reveals other ways of checking the kind of an object and preserving the code straightforward to know whereas additionally decreasing the probabilities of introducing hard-to-spot bugs. […]

Highlight your code snippets using [code lang="language name"] shortcode. Just insert your code between opening and closing tag: [code lang="java"] code [/code]. Or specify another language.

Subscribe to foojay updates:

https://foojay.io/feed/
Copied to the clipboard