← Back to quizzesFree quiz

Polymorphism and Equality in Java

Polymorphism, method overriding, overloading, and object equality are core concepts every Java developer must master. This course breaks down each idea, explains common pitfalls, and…

10 questions~5 min
Polymorphism and Equality in Java — Qwi
0 / 10
Score: 0%
1

When a subclass overrides a method, how can the subclass invoke the original superclass implementation within its overriding method?

2

Given class Ball with fields int x, y and method moveTo(int x, int y), what will be printed when calling moveTo(30, 40) if the method prints the parameters?

3

Why is it generally advisable to override the toString() method in a custom class?

4

Which of the following statements about the == operator for objects in Java is correct?

5

If a subclass method has the same name and parameter types as a superclass method but a different return type, what will happen?

6

When overriding a method, why must the overriding method not be more private than the method it overrides?

7

Consider two distinct objects of class Thing created with new Thing(). Using the equals() method without overriding, what will be the result of thing1.equals(thing2)?

8

Which of the following best describes method overloading?

9

What is the effect of variable shadowing in the following method signature: void moveTo(int x, int y) when the class also has fields int x, y?

10

Why should you override equals(Object o) in your own classes when you need logical equality?

Understanding Polymorphism and Equality in Java

Polymorphism, method overriding, overloading, and object equality are core concepts every Java developer must master. This course breaks down each idea, explains common pitfalls, and provides practical examples that align with typical quiz questions. By the end, you’ll be able to write clear, maintainable Java code and avoid subtle bugs related to inheritance and comparison.

1. Invoking Superclass Implementations from Subclasses

When a subclass overrides a method, the original behavior defined in the superclass is still accessible via the super keyword. This is essential when you want to extend functionality rather than replace it entirely.

  • Correct approach: super.methodName();
  • Common mistake: casting the subclass to the superclass and calling the method. This merely changes the reference type; the overridden method in the subclass will still be executed.
  • Why super works: The Java compiler binds super.methodName() to the superclass’s implementation at compile time, bypassing dynamic dispatch.

Example:

class Animal {
    void speak() { System.out.println("Animal sound"); }
}

class Dog extends Animal {
    @Override
    void speak() {
        super.speak(); // Calls Animal.speak()
        System.out.println("Woof!");
    }
}

2. Parameter Passing and Method Output

Java methods receive arguments by value. When a method like moveTo(int x, int y) prints its parameters, the output reflects the values passed at the call site, not the object's internal fields unless you explicitly use them.

  • Calling moveTo(30, 40) will print "moving ball to 30+40" if the method prints the parameters directly.
  • If you need to update the object's state, assign the parameters to the fields inside the method before printing.

3. Overriding toString() for Better Debugging

The default Object.toString() returns a cryptic string like ClassName@1a2b3c. Overriding it provides a human‑readable representation of an object's state, which is invaluable for logging, debugging, and interactive sessions.

  • Benefit: Quickly understand object contents without stepping through code.
  • Typical implementation:
@Override
public String toString() {
    return "Ball{x=" + x + ", y=" + y + "}";
}

4. The == Operator vs. equals()

In Java, == compares reference identity for objects, meaning it checks whether both variables point to the exact same memory location.

  • It does not compare the logical content of objects.
  • For value comparison, override equals() and use it explicitly.
  • Special case: primitive types (int, boolean, etc.) are compared by value with ==.

Example:

String a = new String("hello");
String b = new String("hello");
System.out.println(a == b);          // false – different objects
System.out.println(a.equals(b));    // true – same character sequence

5. Return‑Type Compatibility in Overriding

When a subclass overrides a method, the return type must be either identical to or a covariant (subtype) of the superclass method’s return type. Changing it to an unrelated type triggers a compilation error.

  • Key rule: ON SR – Only Same Return (or Subtype).
  • Covariant returns enable more specific return types, e.g., overriding Object clone() with MyClass clone().
  • Attempting to return a completely different type, such as String when the superclass returns Integer, is illegal.

6. Access Modifiers and Overriding

The overriding method cannot be more restrictive than the method it overrides. Doing so would violate the Liskov Substitution Principle (LSP) and cause compile‑time access errors.

  • Example: A public method in a superclass must remain public in the subclass.
  • Making it protected or private would hide the method from callers expecting the broader visibility.

7. Default equals() Behavior

If you do not override equals(), the implementation inherited from Object uses reference equality. Therefore, two distinct instances of the same class will return false when compared with equals().

  • To compare field values, provide a custom equals() that checks each relevant attribute.
  • Always pair equals() with a consistent hashCode() implementation.

8. Method Overloading Explained

Method overloading occurs when a class defines multiple methods with the same name but different parameter lists (type, number, or order). It is resolved at compile time, allowing the compiler to choose the most specific signature based on the arguments supplied.

  • Return type differences alone do not constitute overloading.
  • Overloading improves API readability and provides flexibility without sacrificing type safety.
class Calculator {
    int add(int a, int b) { return a + b; }
    double add(double a, double b) { return a + b; }
    int add(int a, int b, int c) { return a + b + c; }
}

9. Summary of Key Takeaways

  • Use super.methodName() to call a superclass implementation from an overriding method.
  • Method parameters are printed exactly as passed; internal fields are unchanged unless explicitly assigned.
  • Overriding toString() yields meaningful object descriptions for debugging.
  • == checks reference identity; use equals() for logical equality.
  • Overridden methods must keep the same or a covariant return type; otherwise, compilation fails.
  • Visibility cannot be reduced when overriding; maintain at least the same access level.
  • Default equals() uses reference equality; customize it for field‑by‑field comparison.
  • Method overloading requires distinct parameter lists and is resolved at compile time.

10. Frequently Asked Questions (FAQ)

Can I overload a method with the same parameter types but a different return type? No. Overloading requires a change in the parameter list; the return type alone is insufficient. Is it ever safe to use == for String comparison? Only when you are certain both references point to the same interned String literal. Otherwise, use equals(). What happens if I forget to call super() in a subclass constructor? The compiler inserts a call to the no‑argument superclass constructor automatically. If the superclass lacks such a constructor, you must explicitly call an appropriate super(...).