Overriding toString()

Figure 475. Shape log info Slide presentation Create comment in forum
public class Run {
  static final Logger log = LogManager.getLogger(Run.class);
  public static void main(String[] args) {
    final double x = 2.0, y = 3.0;
    final Shape shape = new Shape(x, y);
    log.info(shape);  ...
2017... INFO  [main] inherit.Run ... - inherit.Shape@37d31475

Desired:

2017... INFO  [main] inherit.Run ... - (2.0|3.0)

Figure 476. Overwriting toString() Slide presentation Create comment in forum

Figure 477. Shape extending Object Slide presentation Create comment in forum

Figure 478. Logging Rectangle instances Slide presentation Create comment in forum
public class Run {
  static final Logger log = LogManager.getLogger(Run.class);
  public static void main(String[] args) {
    final double x = 2, y = 3, width = 3., height = 4.;
    final Rectangle r = new Rectangle(x, y, width, height);
    log.info(r); ...
2017 ... INFO  [main] inherit.Run (Run.java:15) - (2.0|3.0)

Desired:

2017 ... INFO  Rectangle at (2.0|3.0), width= 3.0, height=4.0

Figure 479. Override toString() again. Slide presentation Create comment in forum
public class Rectangle extends Shape {
  @Override public String toString() {
    return "Rectangle at " + super.toString()  +
      ", width= " + width + ", height=" + height; 
  } ...

The super keyword allows for calling the toString() method from superclass Shape.

Append class Rectangle's own width and height attributes.


Figure 480. Rectangle extending Shape Slide presentation Create comment in forum

Figure 481. Implementing Circle.toString() Slide presentation Create comment in forum
public class Circle extends Shape {
  /**
   * Creating a circle of given center and radius
   * @param x Center's x component.
   * @param y Center's y component.
   * @param radius The circle's radius.
   */
  public Circle(double x,double y, double radius) {
    super(x, y);
    this.radius = radius;
  }
  @Override public String toString() {
    return "Circle at " + super.toString() +", radius= " + radius;
  }
  private double radius;
}

Figure 482. Shape and toString() Slide presentation Create comment in forum
Shape and toString()

exercise No. 157

String vs. StringBuffer Create comment in forum

Q:

Consider two StringBuffer instances:

Code Execution result
final StringBuffer
  a = new StringBuffer("test"),
  b = new StringBuffer("test");

System.out.println(a.equals(b));
false

Strangely instances of String behave differently:

Code Execution result
final String
  a = new String("test"),
  b = new String("test");

System.out.println(a.equals(b));
true

Explain this different behaviour.

Tip

Take a closer look at the String and StringBuffer API regarding the toString() method.

A:

The String API reveals:

public boolean equals (Object anObject)
Compares this string to the specified object. The result is true if and only if the argument is
not null and is a String object that represents the same sequence of characters as this object.

Overrides: equals in class Object

Parameters:
anObject - The object to compare this String against

Returns:
true if the given object represents a String equivalent to this string, false otherwise

In a nutshell: Two instances of String will be compared for equality character by character. The superclass Object.equals() method is being overridden.

In class StringBuffer we do not find any equals() method. Thus Object.equals() is not being overridden. When comparing two instances of StringBuffer effectively Object.equals() will be executed. Its API reveals:

public boolean equals (Object obj)
Indicates whether some other object is "equal to" this one.
...
Parameters:
obj - the reference object with which to compare.
Returns:
true if this object is the same as the obj argument; false otherwise.

Thus two instances of StringBuffer will be compared for object identity rather than representing the same string value.

exercise No. 158

Alternate implementation of opposite directions Create comment in forum

Q:

Provide a different implementation of your opposite() from Compass direction neighbours . Follow https://stackoverflow.com/questions/5678309/illegal-forward-reference-and-enums#answer-49409377. Start by investigating both values() and ordinal().

A:

We observe the following ordinal values:

public enum Direction {

  N(   0, "north"),         // 0
  NE( 45, "north by east"), // 1
  E(  90, "east"),          // 2
  SE(135, "south by east"), // 3
  S( 180, "south"),         // 4
  SW(225, "south by west"), // 5
  W( 270, "west"),          // 6
  NW(315, "north by west"); // 7
...
public Direction opposite() {
    switch (this) {
      case N: return S;   // 0 --> 4
      case NE: return SW; // 1 --> 5
      case E: return W;   // 2 --> 6
      case SE: return NW; // 3 --> 7
      case S: return N;   // 4 --> 0
      case SW: return NE; // 5 --> 1
      case W: return E;   // 6 --> 2
      case NW: return SE; // 7 --> 3
      ...

We are thus left implementing an integer shift (0, 1, 2, 3, 4, 5, 6, 7) to (4, 5, 6, 7, 0, 1, 2, 3):

public Direction opposite() {
     return values()[ (ordinal() + 4) % 8];
}