History of the Question
Pattern matching is a technique borrowed from functional and scripting languages that allows checking the type and extracting data in a single step. In Java, the development of pattern matching began with Java 14 (preview feature), improved in Java 16–17, and is being expanded in the latest releases to include switch.
Problem
The classic way of checking the type and casting looked cumbersome:
if (obj instanceof String) { String s = (String) obj; ... }
This resulted in unnecessary variables, a lot of boilerplate code, and the risk of casting type errors.
Solution
Pattern matching allows combining type checking, declaring a new variable, and using it all in one expression:
if (obj instanceof String s) { System.out.println(s.length()); }
Similar patterns now appear in switch constructs, making the code more concise and less prone to errors.
Key features:
Can pattern matching be used for custom classes or only for standard types?
It can be used for any classes. Pattern Matching works for all classes where instanceof can be applied.
Will the pattern variable be accessible outside the if/switch block?
No, the variable declared inside pattern matching is only visible within the block where it was created (e.g., inside if or switch case).
Example code:
if (obj instanceof Integer i) { // i is only visible in this block System.out.println(i + 10); } // Here i is not accessible
Can pattern matching be used with generics?
Yes, like this:
Object list = List.of("a", "b"); if (list instanceof List<?> l) { System.out.println(l.size()); }
However, working with raw types and casting to parameterized types is still limited due to type erasure.
The team implemented pattern matching in all cases, including internal DTOs, service classes, and cases where polymorphism would have sufficed. The code became too dependent on instanceof, and the role of class hierarchies was blurred.
Pros:
Cons:
In the project, pattern matching was applied only for general interfaces, utility helpers, and handling collections of unknown types. The OOP architecture was maintained, using the pattern only where it was unavoidable.
Pros:
Cons: