3

I have Point class as the following code:

public class Point {
    private final int x;
    private final int y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Point point)) return false;
        return x == point.x && y == point.y;
    }

    @Override
    public int hashCode() {
        return Objects.hash(x, y);
    }
}

The equals function is generated by IntelliJ, which can also accept a subclass of Point as a parameter. But I don't understand the meaning of if (!(o instanceof Point point)). Why is there point after Point, and how is point defined in the equals function?

QBrute
  • 4,405
  • 6
  • 34
  • 40
Elias
  • 179
  • 8
  • 11
    [Pattern matching for `instanceof`](https://docs.oracle.com/en/java/javase/17/language/pattern-matching-instanceof-operator.html) – QBrute Apr 19 '23 at 10:46
  • does this: if (!(o instanceof Point point)) actually compile? My guess, you meant to type: if (!(o instanceof Point)) – Stultuske Apr 19 '23 at 10:47
  • 3
    @Stultuske They didn't "mean to type" anything, because it was generated by IntelliJ. The declaration of the `point` variable is necessary for the line below that. See [the part of the JEP starting "The flow scoping analysis..."](https://openjdk.org/jeps/394) – Michael Apr 19 '23 at 10:57
  • 4
    I'm still getting accustomed to the fact that the scope of the pattern variable can extend beyond the statement it's declared in. – tgdavies Apr 19 '23 at 11:07
  • @Michael which version was this added in? – Stultuske Apr 19 '23 at 11:33
  • 1
    @Stultuske It was introduced as a preview feature in version 14: https://openjdk.org/jeps/305 – QBrute Apr 19 '23 at 11:43

1 Answers1

4

This is called "Pattern matching for instanceof".

I am going to assume you know the previous syntax which would be.

if( !(o instanceof Point) ) return;

Point point = (Point)o;

return x == point.x && y == point.y;

As of java 16 there is a new syntax that is supposed to be a bit more concise.

if( !(o instanceof Point point) ) return;

return x == point.x && y == point.y;

Instead of casting and creating a local variable, you can declare the variable within the instanceof statement.

The scope of the pattern variable is described as "flow scoping" in JEP 394 which can be a bit non-intuitive. Pattern Matching for instanceof has more examples.

matt
  • 10,892
  • 3
  • 22
  • 34
  • 1
    I knew the feature but hadn't realized that its scoping rules are different, TIL! But the link you provided doesn't mention "flow scoping" by that name. Do you have a source for that name? Especially for new features I'd like to be very specific and "correct" when I talk about them. – Joachim Sauer Apr 19 '23 at 12:18
  • 4
    @JoachimSauer [JEP 394](https://openjdk.org/jeps/394) mentions this term a few times. – QBrute Apr 19 '23 at 12:24