## The instanceof operator

Figure 480. Defeating polymorphism
 public static void main(String[] args) { final Shape[] shapes = { new Circle(1, 1, 2.), new Rectangle(1, -1, 2., 3.)}; print(shapes); } static void print(final Shape[] shapes) { for (final Shape s : shapes) { if (s instanceof Rectangle) { System.out.println("Type Rectangle"); } else if (s instanceof Circle) { System.out.println("Type Circle"); } } } Type Circle Type Rectangle

Figure 481. Defining equals(...): Expectations
Rectangle r1 = new Rectangle(1, 2, 5, 4),
r2 = new Rectangle(1, 2, 1, 7),
r3 = new Rectangle(1, 2, 5, 4);

Circle c = new Circle(-2, 3, 5);

System.out.print(r1.equals("Hi"));//false: Differing classes Rectangle and String.
System.out.print(r1.equals(r2));  //false: Differing width and height.
System.out.print(r3.equals(r1));  //true:  Two rectangles having identical
//       (x|y), width and height.
System.out.print(r1.equals(c));   //false: Differing classes Rectangle and Circle.
System.out.print(c.equals(c));    //true: Object equal to itself.

Figure 482. Defining equals(...) of Shape instances

Two Shape instances shall be considered equal if:

• Both instances are of common type i.e. either Rectangle or Circle.

• Their center coordinates match within a threshold of $10 - 15$.

• width and height or radius match within a threshold of $10 - 15$.

Figure 483. Comparing center coordinates
public abstract class Shape {
private double x, y;

protected boolean equalCenter(final Shape o) {
return Math.abs(o.x - x) + Math.abs(o.y - y) < 1.E-15;
}
...

Figure 484. Implementing Rectangle.equals()
public class Rectangle extends Shape {
@Override public boolean equals(Object o) {
if (o instanceof Rectangle) {

final Rectangle oRectangle = (Rectangle) o; // Cast is «legal»
return super.equalCenter(oRectangle) &&
Math.abs(oRectangle.width- width) +
Math.abs(oRectangle.height- height) < 1.E-15;
}
return false;
}
...

For o == null the expression o instanceof Rectangle evaluates to false. No. 174

### Why is oRectangle = (Rectangle) o a legal cast?

 Q: We consider:Object o = new Scanner(System.in); String s = (String) o;On execution we receive a java.lang.ClassCastException: Exception in thread "main" java.lang.ClassCastException: class java.util.Scanner cannot be cast to class java.lang.String at q.App.main(App.java:20)The comment in Figure 484, “Implementing Rectangle.equals() ” states the following cast to be legal: final Rectangle oRectangle = (Rectangle) o; // Cast is «legal»Why is this claim indeed true? Don't try digging too deep: The answer is quite simple. A: The cast in question appears within the following if block: if (o instanceof Rectangle) { final Rectangle oRectangle = (Rectangle) o; ... }Thus the cast will only be executed if our variable o actually refers to an instance of class Rectangle. In other words: The if block guards our code against illegal cast attempts. Rewriting our faulty code accordingly also removes the initial example's runtime exception: Object o = new Scanner(System.in); if (o instanceof String) { String s = (String) o; // Unreachable code }
Figure 485. Implementing Circle.equals()
public class Circle extends Shape {
@Override public boolean equals(final Object o) {
if (o instanceof Circle){
final Circle oCircle = (Circle) o;
return super.equalCenter(o) &&
} ...
Figure 486. Testing equality of Shape objects
 final Rectangle r1 = new Rectangle(2, 3, 1,4), r2 = new Rectangle(2, 3, 2,8), r3 = new Rectangle(2, 3, 1,4); final Circle c = new Circle(2,3, 7); System.out.println("r1.equals(r2): " + r1.equals(r2)); System.out.println("r1.equals(r3): " + r1.equals(r3)); System.out.println("c.equals(r1): " + c.equals(r1)); r1.equals(r2): false r1.equals(r3): true c.equals(r1): false