Strange equality behavior in java

Take a look at the following code:

Long minima = -9223372036854775808L; Long anotherminima = -9223372036854775808L; System.out.println(minima==anotherminima); //evaluates to false System.out.println(Long.MIN_VALUE); Long another= 1L; Long one = 1L; System.out.println(another == one); //evaluates to true 

I can not understand this behavior ..? I was hoping that the first assessment would also be true. And that is what I expect.

+5
source share
6 answers

There is a caching method used by the JVM for a range of autoboxing values. As stated in the specification ( http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.7 )

If the p value in the box is true, false, a byte or char in the range from \ u0000 to \ u007f or int, or a short number between -128 and 127 (inclusive), then let r1 and r2 be the results of any two p box transforms. It always happens that r1 == r2.

Ideally, boxing a given primitive p value will always give an identical reference. In practice, this may not be possible using existing implementation methods. The rules above are a pragmatic compromise. The final final sentence requires that certain common values โ€‹โ€‹always be placed in indistinguishable objects. An implementation can cache these, lazily or impatiently. For other values, this statement prohibits any assumptions about the identity of nested values โ€‹โ€‹in the programmer's part. This would allow (but not require) the sharing of some or all of these links.

This ensures that in most common cases, behavior will be desirable without imposing an excessive performance penalty, especially on small devices. Less memory-limited implementations can, for example, cache all char and short values, as well as int and long values โ€‹โ€‹in the range from -32K to + 32K.

So, 1L is in these cached values, and then autoboxing gives the same link, but in the case of a number outside this range (e.g. Long.MIN_VALUE) it is not cached and therefore a different instance / link.

In any case, when comparing an object, you should always use .equals ()

+4
source

Just guess here, but it may be that 1L is in a constant pool, and therefore referential equality evaluates to true (just like sometimes even Strings, == will evaluate to true), while the other huge numbers are not. You do not know how to check which constants are in the pool during initialization.

Edit: Java has a cache of defined constant objects (including wrapper classes for primitives and String). So if you write

 String st1 = "A"; 

if "A" is in a constant pool, Java will not create a new String object - it will simply create a link to an existing one. So if you did then

 String st2 = "A"; System.out.println(st1 == st2); 

He will print the truth.

Now not all are integers, long, short, etc. cached (there are too many), but lower values. Therefore, I would suggest that 1L is. This means that in your question, both another and one refer to the same object, and thus it returns true even for reference equality.

+2
source

First of all, you should use long instead of long . Secondly == between Integer, Long, etc. Will check referential equality. You can check 5.1.7 Boxing Conversion . Alo 1L is in the constant pool , so the second case returns true.

On the side of the note, you should use .equals to compare the long.

From Oracle docs:

If the value of p placed in the field is true, false, a byte or char in the range \ u0000 to \ u007f, or int or a short number between -128 and 127 (inclusive), then let r1 and r2 be the results of any two conversion conversion boxes . It always happens that r1 == r2.

Ideally, boxing a given primitive p value will always give an identical reference. In practice, this may not be possible using existing implementation methods. The rules above are a pragmatic compromise. The final final sentence requires that certain common values โ€‹โ€‹be always inserted into indistinguishable objects. [...]

This ensures that in most common cases the behavior will be desired without introducing an excessive execution penalty, especially on small devices. Smaller implementations limited by memory can, for example, cache all char and short values, as well as int and long values โ€‹โ€‹in the range from -32K to + 32K.

+2
source

Problem:

 (minima==anotherminima) 

You are comparing the memory location of an object, not its value, so it returns false .

If you want to compare two long shell classes, you need to call compareTo

From jls

 If the value p being boxed is true, false, a byte, or a char in the range \u0000 to \u007f, or an int or short number between -128 and 127 (inclusive), then let r1 and r2 be the results of any two boxing conversions of p. It is always the case that r1 == r2. 

Now, if you use -128 and 127 to initialize the Long wrapper class, this will convert the box that will have the same reference.

0
source

Adding to this answer , everything from -128 to 127 is cached into the instance in constant java memory, which means that these numbers (almost) always have reference equality, because no new instances have been created for them. Outside the cache, every time a number is used, a new instance is created, so they are not equal by reference. More here and here

0
source

You should use long instead of long . Note that long is a class, so you should use equals() to compare its instances. On the other hand, if you use long instead, you can compare with == , because these are primitives.

-2
source

Source: https://habr.com/ru/post/1201007/


All Articles