0

So when we are comparing objects, we use equals() methods, or something similar in an if statement for example. If we have the following code

String a = "foo";
String b = "foo";
return a==b

we would get false returned to us because a and b refer to different objects. On the other hand,

String a = null;
return a == null

we would get true. Why is that?

Meepo
  • 368
  • 4
  • 19
  • Incidentally, your first example uses a compiler optimization for string literals which makes your first code snippet return `true`. – 4castle Apr 21 '17 at 01:56
  • see http://stackoverflow.com/questions/1894149/is-null-an-object – Scary Wombat Apr 21 '17 at 01:56
  • I think this can be boiled down to "null is special". http://stackoverflow.com/a/1894291/2310289 – Scary Wombat Apr 21 '17 at 01:57
  • Which java version are you using – Fangxing Apr 21 '17 at 01:58
  • 1
    @fangxing, I don't think it has anything to do with the java version. – Devendra Lattu Apr 21 '17 at 02:00
  • @ScaryWombat I understand that null isn't an object, but doesn't the string object still point to something? And if so, does the reason why it works if because String a and null both point to the same location in memory? – Meepo Apr 21 '17 at 02:00
  • Yes, see @ghostCat answer below – Scary Wombat Apr 21 '17 at 02:03
  • 1
    @4castle - It is not a "compiler optimization". It is a mandatory behavior that is specified in the Java Language Specification. Any "java" implementation that doesn't give `true` is NOT JLS compliant. – Stephen C Apr 21 '17 at 02:21
  • Uh, @StephenC 4castle was specifically talking about the first example. By technicality, the first example would return true in a compiler like eclipse, but the fundamental way that java works, it should return false like I said in my question. – Meepo Apr 21 '17 at 02:23
  • 1
    @AlphaGamergate No. It *must* return true, in any version of Java. Eclipse has nothing do with it, and neither does 'by technicality'. – user207421 Apr 21 '17 at 02:25
  • 1
    @AlphaGamergate it is not a 'technicality', as people keep trying to tell you. See this answer with language spec references. http://stackoverflow.com/questions/3451145/when-are-java-strings-interned – pvg Apr 21 '17 at 02:27
  • @StephenC Would you say it's a "mandatory compiler optimization"? – 4castle Apr 21 '17 at 02:34
  • @AlphaGamergate - Basically, your whole question is based on a misunderstanding of Java. If you correct your misunderstanding, you will see that the case where you compare a string with `null` using `==` is ... nothing special. – Stephen C Apr 21 '17 at 02:36
  • @4castle - I wouldn't. – Stephen C Apr 21 '17 at 02:37
  • Wait now I'm really confused. I was always taught that if two Strings had the same value, using the == operand wouldn't give true because they pointed to different things. I am heartbroken. – Meepo Apr 21 '17 at 02:37
  • @AlphaGamergate - if that is what you were taught, that is only partly correct. The reason not to use `==` is that two "equal" strings **may** be different objects. String literals are a special case. If two string literals are equal, then they will be the same object. – Stephen C Apr 21 '17 at 02:39
  • @4castle It is a mandatory feature of both the compiler and the class loader, that has defined semantic effects. Compiler optimizations are not permitted to cause perceptible semantic differences. – user207421 Apr 21 '17 at 02:41
  • Ok everybody, Strings were just an example. Let's make a new object okay? Say we created a object with the field int i. If I made two objects and set i to the same thing and used == to compare them, it would be false. Ok guys? The fact that I use Strings doesn't matter. In general, == gives false between two objects with different pointers – Meepo Apr 21 '17 at 02:42
  • @EJP - I think it is a matter of "battling definitions" for what is or is not a "compiler optimization". I'm not going to say that he should not describe this as a "mandatory compiler optimization" .... but I wouldn't do that myself. – Stephen C Apr 21 '17 at 02:44
  • 1
    @AlphaGamergate - If that is what you meant to ask ... then you FAILed. Next time, check that your example is correct before you post it. I am voting to close this Question as "unclear". – Stephen C Apr 21 '17 at 02:46
  • @StephenC My question title clearly states OBJECT. I use the word OBJECT several times. I now have to accept that there is no good answer and it simply is. – Meepo Apr 21 '17 at 02:49
  • And your example is clearly wrong. Since you base your entire argument on the example, the question is unclear. – Stephen C Apr 21 '17 at 02:50
  • @AlphaGamergate Rubbish. All you have to accept is that you are conflating objects and references, and that the behaviour of string literals and `null` it is specified in the JLS. That is the answer, and you've been given it several times. – user207421 Apr 21 '17 at 02:51
  • @EJP and JLS says it works. That's it. I mean logically it makes sense. But I was hoping for a more mechanical reason for it. – Meepo Apr 21 '17 at 02:52
  • The mechanics are an >>implementation<< of the specification. Not the other way around. But ... the mechanical explanation is basically the same. The address that represents the null reference (typically) is not an address of the representation of any valid Java object. (Why? because the JLS says it *shouldn't be*.) – Stephen C Apr 21 '17 at 02:58
  • At this point my question comes down to how they implement null and we don't have that. – Meepo Apr 21 '17 at 02:59
  • The answer to that is ... implementation dependent. Different implementations of Java implement references in different ways. Sometimes they are addresses, sometimes they are compressed addresses, sometimes they are indexes into an table. Seriously. I have seen / worked with all three kinds. The implementation / representation of `null` is potentially different in each case. However, all implementations of `null` behave like the JLS says they should. That is why you should base your understanding on the JLS ... not a flakey mental model of one style of implementation. – Stephen C Apr 21 '17 at 03:02
  • @StephenC ok thank you. That was what I was looking for. I understand that my question was truly about implementation and I'm only going to get links to JLS. – Meepo Apr 21 '17 at 03:03
  • 1
    I had the same exact question when I was a beginner in Java, I can't understand why would someone downvote such an interesting question. Thanks for the question! – Vaggelis Manousakis Oct 05 '18 at 19:51

4 Answers4

5

Why does Object == null work?

This doesn't really mean anything. Objects aren't values in Java. You can't write that. All you can write is someObjectReference == null.

So when we are comparing objects

We aren't. See above. We are comparing references.

we use equals() methods, or something similar in an if statement for example. If we have the following code

String a = "foo";
String b = "foo";
return a==b

we would get false returned to us because a and b refer to different objects.

No we wouldn't, and no they don't. It will return true. Try it. String literals are pooled by Java. There is only one "foo" object.

On the other hand,

String a = null;
return a == null

we would get true. Why is that?

Because the value of the reference a is null, and so is the value of expression on the RHS of the == operator. Equal values => result of == is true. Note that a is a reference, not an object.

user207421
  • 305,947
  • 44
  • 307
  • 483
4

Because two different references can point to the same content. Then the objects are equal, but the references are still different.

But when the references are the same, then we'll, there is only one reference.

Given your example:

Object o = new Object();
Object o2 = o;
return  o == o2

would result in?!

GhostCat
  • 137,827
  • 25
  • 176
  • 248
  • Ok, I understand some reference semantics. I get that the two objects can have the same value and thus equal, but the references are different and the == operand only compares the references. But null isn't a reference is it? And wouldn't two references to null be different? Also, in answer to your question, it would result in true since o2 points to o. I understand that. – Meepo Apr 21 '17 at 02:03
  • 2
    @AlphaGamergate All `null` values are equal. – 4castle Apr 21 '17 at 02:06
  • But I get your point. And I think some of the links from the comments address that "null is special" topic. I might include some more information about that when I get my hands on a real keyboard. – GhostCat Apr 21 '17 at 02:09
  • @4castle yes, but why? – Meepo Apr 21 '17 at 02:09
  • 1
    @AlphaGamergate I'm glad you asked. It's because the [Java Language Specification says so](https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.21.3). It's not specified how `null` is implemented, just that all references to it must be considered equal. – 4castle Apr 21 '17 at 02:12
  • @4castle `null` is not an object. It is a special *value* of a *reference*. There is no such thing as a a reference to null. It is a reference whose *value* is null. See your own reference. – user207421 Apr 21 '17 at 02:15
  • @EJP The JLS describes the `null` literal as a [`null` reference](https://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.10.7). – 4castle Apr 21 '17 at 02:17
  • @4castle Exactly. *Not* as a reference *to* anything. – user207421 Apr 21 '17 at 02:19
  • @4castle ok this makes sense. I wish there was a more concrete answer since I know that in C null is actually a point to a specific location in memory, and that everything that is null points to the same thing, but I know that Java was different. – Meepo Apr 21 '17 at 02:19
  • 1
    @AlphaGamergate That's not correct either. In C, null is a special value of a pointer, represented in the source code (but not necessarily at runtime) by zero. It doesn't point *to* anything, and there is no 'specific location in memory' for it. The situation in Java is exactly the same, with `null` instead of the zero. – user207421 Apr 21 '17 at 02:22
  • 1
    Indeed, in a typical C implementation, the null pointer points to something that is NOT a valid memory location. That's why you get a SIGSEGV when you try to deference a null pointer. – Stephen C Apr 21 '17 at 02:24
  • @EJP and Stephen, I stand corrected. I guess I misinterpreted the zero in the source code and thought it was a reference to memory. – Meepo Apr 21 '17 at 02:28
  • @EJP IMO saying "null is not a reference, because it doesn't refer to anything" is like saying "zero is not a number, because it has no quantity". I don't see why it needs to be so complicated. It's a reference to nothing, and all nothings are equal. – 4castle Apr 21 '17 at 02:30
  • @4castle Nobody has uttered the quotation you have just fabricated. You are arguing with the JLS. You are also contradicting yourself, and arguing in circles. There is no difference between 'not a reference to anything' and 'reference to nothing'. Please stop this. – user207421 Apr 21 '17 at 02:39
  • @EJP Your original statement was that "there is no such thing as a reference to null", which I'm disputing, because a reference to null would be the null reference. – 4castle Apr 21 '17 at 02:46
  • @4castle I know what my original statement was, thanks, and I don't need it twisted around into a fabricated quotation. My original statement was correct and is backed up by the JLS. A reference *is* null, *or* refers to an object. – user207421 Apr 21 '17 at 02:48
  • @EJP Okay, I think I see the point of misunderstanding. When I say "a reference to null", I'm not referring to "null" the reference, but "null" the quantity. Sorry for the misunderstanding. It's a difficult subject to talk about since it has a meaning in English as well as Java. – 4castle Apr 21 '17 at 03:34
2

I think null represents a variable that does not point to anything in the heap memory。So, if a = null, then a == null returns true is justified,because a does not point to anything, and also null.

  • Hmmm, ok this makes sense. So what's going on is that a == null means that a has no reference, so we are comparing an object that has no reference to another thing that has no reference? – Meepo Apr 21 '17 at 02:18
0

Additionally,

String s1 = new String("test");
String s2 = "test";
String s3 = null;

Check:

s1 instanceof String // true, s1 is String object and we allocated a memory to it.
s2 instanceof String // true, s2 is String object and we allocated a memory to it.
s3 instanceof String // false, because we did not allocate memory to object of String s3

s1 == null           // false, we allocated a memory to the String object s1
s2 == null           // false, we allocated a memory to the String object s2
s3 == null           // true, because even though s3 is of reference type String, it is null

Note:

s3 instanceof null   // Invalid: as instanceof checks from class name. null is not a class
Devendra Lattu
  • 2,732
  • 2
  • 18
  • 27
  • Yeah..... this doesn't answer my question at all. I think a lot of people are misinterpreting my question as a question about reference semantics, whereas I'm primarily concerned with null! – Meepo Apr 21 '17 at 02:26
  • I understand. Hence, I thought of explaining it through my comments. :) – Devendra Lattu Apr 21 '17 at 02:28
  • @Devendra I get what you were trying to do. I guess the answer is simply that null works that way just cause and we don't really know the underlying mechanism – Meepo Apr 21 '17 at 02:30
  • It is straightforward. Let me know your what further questions you have about `null` – Devendra Lattu Apr 21 '17 at 02:32