Java Interview Questions and Answers
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).
- For primitive data types (like
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 theObject
class checks if two references point to the same object (like==
), but many classes (such asString
,Integer
,List
, etc.) override this method to compare the actual contents of the objects.
- By default, the
-
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 Type | Compares references (memory locations) for objects. | Compares content (state) of objects. |
Used For | Primitives and reference types. | Objects, specifically for comparing contents. |
Default Behavior | Compares 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 Class | Checks 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 (likeString
,Integer
, etc.). Be mindful that some classes, likeString
,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 overridehashCode()
whenever you override.equals()
to maintain consistency between these methods, especially when the objects are used in collections likeHashSet
orHashMap
.
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 likeString
,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 thesound
method from theAnimal
class. - The method
sound()
inDog
provides a new implementation (barking sound) compared to the originalsound()
method inAnimal
. - When the method is called on a
Dog
object, it uses the overridden method, demonstrating polymorphism.
Key Differences Between Method Overloading and Method Overriding:
Feature | Method Overloading | Method Overriding |
---|---|---|
Definition | Multiple methods with the same name but different parameter lists. | A subclass provides its own implementation of a superclass method. |
Method Signature | Methods must differ in number or type of parameters. | Methods must have the same signature (name, return type, parameters). |
Return Type | Return type can differ but does not contribute to overloading. | Return type must be the same or covariant (in case of generics). |
Binding Type | Compile-time (early) binding. | Runtime (late) binding. |
Purpose | Provides different functionalities with the same method name. | Allows subclass to customize or extend superclass behavior. |
Polymorphism | No polymorphism is achieved through overloading. | Achieves runtime polymorphism. |
Access Modifier | Can use different access modifiers (public, private, etc.). | The overriding method cannot have a more restrictive access modifier than the superclass method. |
Usage | Used 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.
Tags
- Java
- Java interview questions
- ArrayList vs LinkedList
- Inheritance in Java
- Method overloading
- Method overriding
- String vs StringBuilder vs StringBuffer
- Multithreading in Java
- Thread creation in Java
- Final keyword in Java
- JSON parsing in Java
- Random number generation in Java
- Comparing strings in Java
- String reversal in Java
- Calculation using switch case
- Remove duplicates in ArrayList
- Exception handling in Java
- Two dimensional array in Java
- Interface vs abstract class in Java
- Java programming basics
- Java collections
- Java performance optimization
- Java data structures