Hacker News new | past | comments | ask | show | jobs | submit login

Can you elaborate on this?

  Integer a = new Integer(2);
  Integer b = a;
Here a == b and no comparison by value.

  Integer c = new Integer(2);
Then a != c but a.equals(c) (in Java). My point is that I do not agree with that and would like to have a == c, which would be the case if '==' was implemented using comparison by value.



While '==' meaning compares equal by value would be nice; it makes the == operator quite complex. If it's a general comparison operator, it would need to recursively compare all the members, and avoid looping on circular references, or risk == running forever.

Certainly, one can come up with examples of how a different operator == would be useful for certain types of objects (including Integer), but the architects of Java strongly felt that an operator should always behave the same, regardless of the type of its operands, unless the operator is + and the objects are Strings.


It's a technical/pedantic point, but

a == b is an value-comparison of the identity "value" (in Java it's the memory reference).

Or in other words, how do I know two references are equal (identity equal) without comparing the values of the references?

Logical equality devolves to the same thing at the end.


> Here a == b and no comparison by value.

Um, nonsense?

    class Intbox {
        public static void main(String[] args) {
    	Integer a = new Integer(2);
    	Integer b = a;
    	System.out.println(a == b);
    	System.out.println(a.equals(b));
        }
    }

    $ java Intbox
    true
    true


I believe what your parent is emphasizing the difference between comparing a == c and a == b. Both are identity comparisons as opposed to value comparisons.

    > cat intbox.java 
    class Intbox {
        public static void main(String[] args) {
            Integer a = new Integer(2);
            Integer b = a;
            Integer c = new Integer(2);
            System.out.printf("a == b => %b\n",  a == b);
            System.out.printf("a.equals(b) => %b\n",  a.equals(b));
            System.out.printf("a == c  => %b\n", a == c);
            System.out.printf("a.equals(c) => %b\n", a.equals(c));
        }
    }

    > javac intbox.java

    > java Intbox
    a == b => true
    a.equals(b) => true
    a == c  => false
    a.equals(c) => true
Edit to add: Your point regarding that "there is no way to compare equal by identity without also comparing equal by value" is true but doesn't really say much. (I'm not sure if it isn't a tautology?) There are cases where one might want to know whether two objects are the same object, or whether they represent the same value. Which you want depends on context.

That's separate from the decision Java made that == was for identity comparison. Some people disagree with that decision.


The point is that equality of identity is objectively more fundamental than equality by any other metric. You can easily observe this by noting that any two objects which are equal in identity are necessarily equal in all other possible ways.

There is no argument to be made that "comparison by value is just as fundamental a concept as comparison by identity", or that this is just a matter of opinion.

The fact that it is possible to compare equal by value without comparing equal by identity does not contradict that it is impossible to compare equal by identity without also comparing equal by value, however you define "equal by value".

> Your point regarding that "there is no way to compare equal by identity without also comparing equal by value" is true but doesn't really say much. (I'm not sure if it isn't a tautology?)

It's not a tautology; it is one of three requirements defining an equivalence relation. (Equivalence relations are by definition reflexive, which is to say x is equivalent to x for all x.)


There are contexts where object identity is meaningless, however. In mathematics, a 2 is a 2 is a 2. This 2 versus this other 2 doesn't have meaning. This can easily trip people up, and arguing that object identity is more fundamental is meaningless. In many contexts, it's the value that's important, and object references actually get in the way. The many discussions on boxed versus unboxed and value types out there are evidence of this.

I agree that in some sense you can say that "identity comparison is more fundamental that value comparison". As I added in my first comment, I think this is likely a tautology, and doesn't do much work for you at the end of the day. The important thing is keeping the two straight and doing the appropriate comparison depending on the context.


In mathematical terms, what I'm saying is that equality is more fundamental than equivalence as defined by some other equivalence relation[1]. If you're considering integers according to their remainder when divided by 5, you can easily show that 4 is equal to 4, and that 4 is equal to -6. If you change your metric to remainder when divided by 3, you'll notice that 4 is still equal to 4, but no longer equal to -6. That is because 4 is fundamentally more similar to 4 than -6 is.

[1] And as I've already mentioned, you can see that this is true by looking at the definition of an equivalence relation. They all treat everything as equivalent to itself.


> any two objects which are equal in identity are necessarily equal in all other possible ways

Two NaNs are equal in identity but not in value, according to the IEEE spec.


I wasn't aware that IEEE floating point provided for two different kinds of equality checking? How would you invoke one or the other?

A NaN value does not compare equal to itself, because NaN is not thought of as a value at all but rather an error signal ("Not a Number"). You can check whether something is NaN, but that's not a distinction between comparing by identity and comparing by value -- it's a distinction between comparing values and checking for the presence of errors. The analogous operations to (1) comparing NaN to itself (unequal) and (2) checking whether NaN is NaN (yes), for another value such as -0, are (1b) comparing -0 to itself (equal) and (2b) checking whether -0 is NaN (no). They aren't (1c) comparing -0 to itself and (2c) checking whether -0 has the same "identity" as -0.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: