🌐
Coderanch
coderanch.com › t › 386368 › java › Equals-Stack-overflow
Equals problem, Stack overflow (Java in General forum at Coderanch)
Maybe that makes sense, and maybe it doesn't. In the example given, B has no other fields besides the reference to A, so if you omit that, there's nothing to compare with. Real-world examples will usually have some other fields - you need to ask yourself, is it sufficient to just compare using the other fields? Is the reference to A really critical to the identity of the object? The answer could be yes or no, depending on what A and B represent. Another option is to write B.equals() so that it depends on == rather than equals() - e.g.
Top answer
1 of 3
2

equals() is a byproduct of an attempt to improve C++ when it was created. C++ has operator overloading which allows you to perform custom operations when called with otherwise valid operators such as <, >, !=, ==, and even =.

The team made the decision (wisely so) to make equality be class method rather than having external static methods as it was done in C++. However, this also meant that equals() coupled with hashCode() defined how such classes were handled in collection classes.

Since any class could in theory override equals() or hashCode(), it means that just because you have a collection of a certain type does not guarantee that behavior is uniform.

For instance, suppose class A has two members x and y used to determine equality. Along comes class B which has x, y, and z. If an instance of B had the same values x and y, how would you go about inserting this instance in a Set? If you call the equals of an instance of A, it will determine the two to be equal and if you call the equals of an instance of B, it will return false since it is not an instance of B.

To be perfectly correct, class B would have to treat member z as an additional condition only in the case in which it is an instance of B, otherwise it lends itself to the equals() method of class A, and, if such a thing is not possible, class B should not allow itself to override equals() or hashCode(). This creates a sticky situation since in theory you should not concern yourself with how the parent class works from an implementation standpoint (if done right anyway), but yet here we are.

You could make class A final to prevent such things from happening, but then of course you can never extend class A. Java makes a point of making certain standard classes like String final to prevent complications of this nature (very smart decision on their part). I think at the end of the day, what matters is that you are very careful in your usage of equals() and hashCode(). I try to use it sparingly, and I am always mindful of which classes I mean to be available in a library and which classes are for internal use as to not to create conditions where things could go horribly wrong.

The Liskov substitution principle is fine in theory, but in practice you can never quite manage it. Take Collection as an example. Collection is implemented by ArrayList, Set, or LinkedList among others. While it is true that you could achieve the same ultimate goal by replacing a Collection with say a HashSet, it is not an ideal implementation for performing operations on all objects contained within (better LinkedHashSet at that point). It wouldn't break existing code, but you may potentially render it grossly inefficient depending on how that Collection is used. Consider that this is a rather clean example too.

If you're lucky, only the implementation details change, but many behave radically different, with some methods throwing a NotImplementedException.

Thus requiring that classes implementing equals() must respect the Liskov substitution principle is asking a lot, and I suspect that they didn't want to alienate the majority of C++ programmers getting familiar with Java.

2 of 3
3

Simple argument against your logic is, what is the use of the equals method if it's modified to be a final. Then it would execute same logic against any given objects. If you want to compare A and AX in the object class what would be the logic?

Overriding of final method is allowed to be able to verify if two different objects (living in 2 different memory locations) are actually equals (== method is there to check if two references are of the same object) based on defined logic. For example if you have a user object like this,

User
{
    string name;
    string email;
    string phone;
}

For one system, it would be the email you might interest to uniquely identifying a user. So you may compare based on email value. But some other system might use phone as the unique identifier. So they may decide to implement different equals methods.

When it comes to logic of A,AX and Liksov substitution principle which is,

Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it.

So if you do,

AX ax1 = new AX();
AX ax2 = new AX();
ax1.equals(ax2);

and

A a = new AX();
AX ax = new AX();
a.equals(ax);

should give you the same output, and it will.

🌐
Stack Overflow
stackoverflow.com › questions › 44472773 › java-not-equals-with-or
Java not equals with OR - Stack Overflow
If name does not equal A or does not equal B - it can't equal both at once, so is always true. — Reverse of "name equals A or B" - clearly a more sensible condition. ... To understand the difference, it always helps to read out your condition ...
🌐
GitHub
github.com › powermock › powermock › issues › 840
StackOverflowError mocking a class with a final equals method · Issue #840 · powermock/powermock
May 21, 2017 - If I mock a class with a final equals() method, the equals() method doesn't get overridden/mocked, potentially causing a stackoverflow error if something in the equals() method references a method on the class. An example of this, removi...
Published   Sep 01, 2017
Find elsewhere
Top answer
1 of 4
5

Yes, == with objects is a reference comparison* (checks if the operands are references to the same object), while equals is whatever the class involved defines it to mean (within the requirements documented for equals). Some classes define equals as being the same as ==, including Java's arrays. (Because they don't override the default implementation from Object.equals, which uses ==.)

If you want to compare Java arrays based on the equality of their contents, you use Arrays.equals instead.

Your experiment would have worked if you used a class that defined equals in a useful way, you were just unlucky picking arrays. It's a bit tricky to find a class in the JVM to use for this experiment, because so many either don't implement equals (like arrays) or could be confusing because there are several immutable classes which may reuse instances (although not if you explicitly use new; but I don't want to go down a path of having you use new with something you probably shouldn't, like String; more on that here). I'm going to give up on picking a good example and use the slightly old class SimpleDateFormat:

DateFormat a = new SimpleDateFormat("yyyy-MM-dd");
DateFormat b = new SimpleDateFormat("yyyy-MM-dd");
System.out.println(a == b ? "== Same" : "== Different");
System.out.println(a.equals(b) ? "equals Same" : "equals Different");

That outputs

== Different
equals Same

because SimpleDateFormat defines equals to check that the other object is also a SimpleDateFormat with the same formatting.

Live example


Re your comment on the question:

I have someone the answer points but I only get the == part, if .equals is checking the content, how come the code didnt print "same" for the second if

Because equals doesn't, necessarily, check content. It only does if a class overrides the default Object.equals (which just uses ==) and implements a content check. Arrays don't. (One could argue that they should have, but they don't.) Other classes, like SimpleDateFormat and String and Integer and HashMap do.

In essence: == is always a reference comparison. equals may or may not be a contents comparison, depending on what class you're using it on.

So for instance, say we have this class:

class Example1
{
    private int content;

    Example1(int content) {
        this.content = content;
    }

    public static void main (String[] args) throws java.lang.Exception
    {
        Example1 a = new Example1(42);
        Example1 b = new Example1(42);
        System.out.println(a == b ? "== Same" : "== Different");
        System.out.println(a.equals(b) ? "equals Same" : "equals Different");
    }
}

Since that class doesn't override equals, you'll get the same answer ("Different") for both == and equals. Live Example.

But if we override equals to define what it would mean for two instances to be equal (in this case: because they have the same content):

class Example2
{
    private int content;

    Example2(int content) {
        this.content = content;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null || !obj.getClass().equals(this.getClass())) {
            return false;
        }
        Example2 other = (Example2)obj;
        return this.content == other.content;
    }

    @Override
    public int hashCode() {
        return this.content;
    }

    public static void main (String[] args) throws java.lang.Exception
    {
        Example2 a = new Example2(42);
        Example2 b = new Example2(42);
        System.out.println(a == b ? "== Same" : "== Different");
        System.out.println(a.equals(b) ? "equals Same" : "equals Different");
    }
}

Now equals says two instances with the same content are the same, because the class defines what that means. Live Example. (Also note that when overriding equals, you must override hashCode, which is why I've done so above.)


* More generally, == tests if the values of its operands are the same. The value in the case of reference types is an object reference, and two object reference values are only the same when they refer to the same object are are only different when they refer to different objects (or one of them is null; not referring to an object at all).

2 of 4
0

To create object you need some portion of memory to store it.

Operator == checks if two variables point to the same memory block. That is they points to the same object instance (they are one person under different aliases).

equals() is a method and checks equality by some algorithm. Meaning two object contain the same data (they are different persons but with the same face, twins for example). Default implementation for java.lang.Object#equals is

public boolean equals(Object obj) {
    return (this == obj);
}

Using you IDE you can ensure that equals for an array is actually java.lang.Object#equals. To check two arrays for equality you should use Arrays.equals. It has also a lot of other useful methods for manipulating with arrays. It is a good idea to check this class first when you need to do something with an array. It saves much time and code lines.

EDITED

Arrays (int[], float[], String[], AnyClass[]) does not implement custom equals method. So for array and for any your custom class equals() and == do same operation unless you override equals() and provide custom comparison. Like

public class Person {
    public String name;
    public String surname;

    public Person(String name, String surname) {
        this.name = name;
        this.surname = surname;
    }

    public boolean equals(Object thatObj) {
        if (thatObj instanceof Person) {
            Person that = (Person) thatObj;
            return this.name.equals(that.name) &&
                this.surname.equals(that.surname);
        }
        return false;
    }
}
🌐
Stack Overflow
stackoverflow.com › questions › 40286061 › java-equals-does-not-work-in-the-way-id-expect-it-to-work
console - Java equals does not work in the way I'd expect it to work - Stack Overflow
Releases Keep up-to-date on features we add to Stack Overflow and Stack Internal. ... Find centralized, trusted content and collaborate around the technologies you use most. Learn more about Collectives ... Bring the best of human thought and AI automation together at your work. Explore Stack Internal ... In my While loop after the first loop it does break out of the While loop but it does not step into my If check, does anyone see what I've done wrong? while (!"Y".equals(inputString) && !"N".equals(inputString)) { inputString = Helper.InputHelper().toUpperCase(); if (inputString.equals("N")) { System.out.println("Thank you for playing!"); System.exit(0); } else if (inputString.equals("Y")) { System.out.println("Starting a new game"); MineSweeper game; game = new MineSweeper(); } }
🌐
Delft Stack
delftstack.com › home › howto › java › not equals java
Not Equals in Java | Delft Stack
March 11, 2025 - When it comes to object comparison, the != operator checks if two references point to different objects in memory. This is crucial in Java, as comparing objects involves more complexity than comparing primitive types.
Top answer
1 of 4
4

Is == checking is slower than equals() in Java?

Comparing two object references is most of time faster but it doesn't make always sense to compare objects in this way.

1) As you compare two int (primitive), the == operator should be favored :

int i = ...;
if(i == 1){

It is the most natural and efficient way.

2) As you compare two Integer(object), the equals()way should be favored:

Integer i =  ...
Integer j =  ...   
if(i.equals(j)){

You have not to use == as == will compare the identity of the objects and it could work in some range but not in all and it depends also on how Integers were instantiated.
So just don't use == in this case.

3) As you compare an Integer with an int, the equals()way should be avoided.

Integer i = ...
if(i.equals(1)){

works but should be avoided as it boxes int 1 to a Integer 1 before invoking equals().
And the equals() method invokes intValue() on the passed Integer argument to equals(). In brief, it performs checks and computations that could be avoided.

You have two ways to handle this comparison case that should have similar performance :

  • Using the == comparison :

    Integer i = ... if (a==1){

    It unboxes the Integer to an int and compares directly the int value with ==

  • using the intValue() of the wrapper and comparing then two primitive ints with ==** (we come back to the first case) :

    Integer i = if(i.intValue() == 1)){

Generally, the automatic unboxing performed by the JVM from an Integer to an int invokes intValue() .

2 of 4
4

The following is not valid:

int i;
int j;

if (i.equals(j))

because primitives are not objects. They have no methods at all; not even equals.

Java has the concept of boxed primitives which are classes which encapsulate a primitive and provide methods you can call. For int the box class is Integer. Using these classes is always slower than using the primitive version but it's sometimes unavoidable. There is an overhead, however slight, to creating objects and making method calls. Primitive values don't suffer from this.

Basically, use primitives unless there's a compelling reason not to.


If the types involved are Integer:

Integer i;
Integer j;

if (i.equals(j))

then you do have an equals method. However, you have (effectively) no choice but to call equals to make this comparison because == is reference equality. You can read more about that here: How to properly compare two Integers in Java? John Skeet's answer talks a little bit about the most efficient way to compare two Integers.

🌐
Myshittycode
myshittycode.com › home › groovy: java.lang.stackoverflowerror when implementing equals()
Groovy: java.lang.StackOverflowError When Implementing equals() | My Shitty Code
January 6, 2023 - The reason we are getting java.lang.StackOverflowError exception is because Groovy overloads == with equals(). So, if (this == o) { … } becomes if (this.equals(o)) { …