Java Interview Questions and Answers

author image Hirely
at 05 Jan, 2025

Question: What is the difference between == and .equals() in Java?

Answer:

In Java, both == and .equals() are used for comparisons, but they work in very different ways and are used for different types of comparisons.


1. == (Reference Comparison):

  • Purpose: The == operator is used to compare references (or memory addresses) of two objects. In other words, it checks whether two variables point to the exact same memory location or object in memory.

  • Usage:

    • For primitive data types (like int, char, etc.), == compares the values directly.
    • For objects (like String, Integer, etc.), == compares whether the two references point to the same object in memory (i.e., whether they are the same instance).

Example:

String s1 = new String("hello");
String s2 = new String("hello");

System.out.println(s1 == s2);  // false, because s1 and s2 refer to different objects in memory

In this case, even though the content of s1 and s2 is the same, == returns false because s1 and s2 are references to different objects in memory.


2. .equals() (Content Comparison):

  • Purpose: The .equals() method is used to compare the content or state of two objects. This method is typically overridden in custom classes to define what it means for two instances of that class to be equal based on their field values.

  • Usage:

    • By default, the .equals() method in the Object class checks if two references point to the same object (like ==), but many classes (such as String, Integer, List, etc.) override this method to compare the actual contents of the objects.
  • Important Note: If you are using .equals() in a custom class, you should override it to define the logic for equality based on the fields of that class.

Example:

String s1 = new String("hello");
String s2 = new String("hello");

System.out.println(s1.equals(s2));  // true, because s1 and s2 have the same content ("hello")

In this case, even though s1 and s2 are different objects, .equals() checks if their contents are the same, and returns true.


Key Differences:

Feature==.equals()
Comparison TypeCompares references (memory locations) for objects.Compares content (state) of objects.
Used ForPrimitives and reference types.Objects, specifically for comparing contents.
Default BehaviorCompares if two references point to the same object in memory.By default, compares if two references point to the same object, but can be overridden to compare actual content.
Example (Primitive)int a = 5; int b = 5; a == b;N/A (Cannot use .equals() on primitive types)
Example (Objects)String s1 = new String("hello"); String s2 = new String("hello"); s1 == s2;String s1 = new String("hello"); String s2 = new String("hello"); s1.equals(s2);
Default in Object ClassChecks if two references are the same (== behavior).Compares object content, but needs to be overridden in custom classes.

Best Practices:

  • For Primitive Types: Always use == for comparison.

  • For Object Comparisons: Use .equals() when you want to compare the contents of two objects (like String, Integer, etc.). Be mindful that some classes, like String, Integer, and others, have already overridden .equals() to compare their contents rather than references.

  • Custom Classes: If you create your own class and need to compare instances for equality, override the .equals() method. Additionally, you should override hashCode() whenever you override .equals() to maintain consistency between these methods, especially when the objects are used in collections like HashSet or HashMap.


Example of .equals() Override in a Custom Class:

class Person {
    String name;
    int age;

    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;  // If they are the same object
        if (obj == null || getClass() != obj.getClass()) return false;
        Person person = (Person) obj;
        return age == person.age && name.equals(person.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}

public class Main {
    public static void main(String[] args) {
        Person p1 = new Person("Alice", 30);
        Person p2 = new Person("Alice", 30);

        System.out.println(p1 == p2);           // false, because they are different objects in memory
        System.out.println(p1.equals(p2));      // true, because they have the same content
    }
}

In this example, we override the .equals() method in the Person class to compare the content of two Person objects based on their name and age.


Conclusion:

  • Use == to compare references (memory locations) or primitives (values).
  • Use .equals() to compare the contents of objects, especially for complex objects like String, List, or custom classes.
  • If you create a custom class and want meaningful content comparison, you should override the .equals() method.

Question: How do you implement method overloading and method overriding in Java?

Answer:

Method overloading and method overriding are two important concepts in Java, both of which allow developers to define methods that share the same name but behave differently. However, they are used in different contexts and serve different purposes.


1. Method Overloading:

Definition: Method overloading in Java occurs when a class has multiple methods with the same name but different parameter lists. Overloading is determined at compile-time and is a way to provide multiple functionalities under the same method name.

Key Points:

  • Methods must have the same name but a different number or type of parameters.
  • Return type can be the same or different, but it is not a factor for overloading.
  • Overloading allows you to perform similar actions with different types or numbers of arguments.

Syntax:

class Calculator {
    // Method to add two integers
    public int add(int a, int b) {
        return a + b;
    }

    // Method to add three integers
    public int add(int a, int b, int c) {
        return a + b + c;
    }

    // Method to add two floating point numbers
    public double add(double a, double b) {
        return a + b;
    }
}

public class Main {
    public static void main(String[] args) {
        Calculator calc = new Calculator();
        
        System.out.println(calc.add(2, 3));       // Output: 5
        System.out.println(calc.add(1, 2, 3));    // Output: 6
        System.out.println(calc.add(2.5, 3.5));   // Output: 6.0
    }
}

Explanation:

  • The add method is overloaded with different parameter lists (two integers, three integers, and two doubles).
  • The method is chosen based on the type and number of arguments passed when it is called.

2. Method Overriding:

Definition: Method overriding occurs when a subclass provides a specific implementation for a method that is already defined in its superclass. The method in the subclass must have the same name, return type, and parameter list as the method in the superclass. Overriding is determined at runtime and is a key feature of polymorphism.

Key Points:

  • Overriding allows a subclass to change the behavior of a method that it inherits from its superclass.
  • The method in the subclass must have the same method signature (name, return type, and parameters) as in the superclass.
  • The @Override annotation is used to indicate that a method is being overridden (although it’s optional, it helps with readability and error checking).
  • Overriding is used to achieve runtime polymorphism.

Syntax:

class Animal {
    public void sound() {
        System.out.println("Animal makes a sound");
    }
}

class Dog extends Animal {
    // Overriding the sound() method of the superclass
    @Override
    public void sound() {
        System.out.println("Dog barks");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal animal = new Animal();
        animal.sound();  // Output: Animal makes a sound

        Dog dog = new Dog();
        dog.sound();     // Output: Dog barks
    }
}

Explanation:

  • The Dog class overrides the sound method from the Animal class.
  • The method sound() in Dog provides a new implementation (barking sound) compared to the original sound() method in Animal.
  • When the method is called on a Dog object, it uses the overridden method, demonstrating polymorphism.

Key Differences Between Method Overloading and Method Overriding:

FeatureMethod OverloadingMethod Overriding
DefinitionMultiple methods with the same name but different parameter lists.A subclass provides its own implementation of a superclass method.
Method SignatureMethods must differ in number or type of parameters.Methods must have the same signature (name, return type, parameters).
Return TypeReturn type can differ but does not contribute to overloading.Return type must be the same or covariant (in case of generics).
Binding TypeCompile-time (early) binding.Runtime (late) binding.
PurposeProvides different functionalities with the same method name.Allows subclass to customize or extend superclass behavior.
PolymorphismNo polymorphism is achieved through overloading.Achieves runtime polymorphism.
Access ModifierCan use different access modifiers (public, private, etc.).The overriding method cannot have a more restrictive access modifier than the superclass method.
UsageUsed when you want to perform the same operation on different types or numbers of arguments.Used when you want to modify or extend the behavior of an inherited method.

Method Overloading Example with Return Type and Parameter Difference:

class Display {
    // Overloaded methods
    public void show(int a) {
        System.out.println("Integer: " + a);
    }

    public void show(String a) {
        System.out.println("String: " + a);
    }

    // Overloaded method with different return type
    public int show(int a, int b) {
        return a + b;
    }
}

public class Main {
    public static void main(String[] args) {
        Display display = new Display();
        
        display.show(5);        // Output: Integer: 5
        display.show("Hello");  // Output: String: Hello
        int result = display.show(3, 4);  // Output: 7
        System.out.println(result);        // Output: 7
    }
}

Conclusion:

  • Method Overloading is when you have multiple methods with the same name but different parameters. It is resolved at compile-time.
  • Method Overriding is when a subclass provides its own implementation for a method defined in the superclass. It is resolved at runtime and is a core feature of polymorphism in object-oriented programming.

Both techniques allow you to write more flexible and reusable code, but they serve different purposes:

  • Overloading allows you to have methods that perform similar operations but with different types or numbers of arguments.
  • Overriding allows you to customize inherited methods in subclasses to provide specific behavior.

Read More

If you can’t get enough from this article, Aihirely has plenty more related information, such as Java interview questions, Java interview experiences, and details about various Java job positions. Click here to check it out.

Related Posts

Trace Job opportunities

Hirely, your exclusive interview companion, empowers your competence and facilitates your interviews.

Get Started Now