To get around the issues created by the testing-casting-instance destruction pattern, Java proposes to embrace pattern matching.
Here's an example of the proposed changes to the language:
Object obj = new Ocean(); // variable type - Object if (obj matches Ocean o) { // check & bind System.out.println(o.getBottles()); // extract }
The preceding code introduces a new Java keyword, matches, which includes a predicate (obj) and a target (Ocean o). The predicate, that is, obj is applied to the target, that is, Ocean o, which binds the o variable to the instance referred by obj. If the matching is successful, you can access members of the instance using the bound variable, that is, o. The following diagram compares the code changes of using instanceof and matches. As is evident, the matches operator takes off the ugly explicit casting from the code:
Let's see whether type matching eases our code with multiple occurrences:
void dyingFish(Object obj) { if (obj matches Ocean o) { // check & bind System.out.println(o.getBottles()); // extract } else if (obj matches Sea sea) { // test System.out.println(sea.getDeadFish()); } else if (obj matches River riv) { // test if (riv.getPlasticBags() > 100) { // cast & destruct System.out.println("Say no to plastic bags. Fish are
dying!"); } } } class Ocean { .. } class Sea { .. } class River { .. }
The test pattern is not limited to the if-else statements. Let's see how it can be used with switch constructs.