I want to compare a long value (primitive type) with another Long value (wrapper type):
long x = 5;
Long y = 5L;
// version 1: only safe, if x is a primitive type
var isEqual = x == y;
// version 2: y needs to be converted to its primitive type
var isEqual = x == y.longValue();
// version 3: using Object.equals(), x will be converted to its wrapper type
var isEqual = Objects.equals(x, y);
The question is:
Is there any benefit in using version 2 instead of version 3?
The advantage of Objects.equals(x, y) is that it covers null cases. The first two would throw a NPE if the Long variable is null.
On the other hand, Objects.equals(x, y) would autobox the long (primitive) argument, hence creating an object. But normally this shouldn't be a concern.
So: just Objects.equals() because the comparison involves a wrapper object and to keep the code simple and readable, otherwise just check for nullability before comparing primitives with Long.longValue().
Related
How we must compare an int wrapper, Integer, to zero value? We can use Integer when the int value can be null (int does not allows null):
Integer x;
both options throw java.lang.NullPointerException:
0 == x; or x == 0;
So, simple, how we can compare Integers that can or not, be null?
x is a field in your class, so when you create it without making it to reference to any Integer object (Integer x = new Integer(7) for example), the compiler gives it a null for you (the default values for Object references). It seems like you have hence: Integer x = null;
So to compare it just use the equals() method that is implemented by Integer wrapper class.
new Integer(0).equals(x)
When I want to compare two variables(One type Object, one type Long), I found that cannot convert Object to Long, for example:
Object obj = 100;
Long l_num = 100L;
System.out.println(obj.equals((Object)l_num)); // print false
System.out.println(((Long)obj) == l_num); // throw java.lang.ClassCastException Exception
Then I can only compare the two with (obj.toString()).equals(l_num.toString()), it returns true.
But, the result is different when I compare Integer with Object:
Object obj = 100;
Integer i_num = 100;
System.out.println(((Integer)obj) == i_num); // return true
System.out.println(obj.equals(i_num)); // return true
System.out.println((obj.toString()).equals(i_num.toString())); // return true
Is there someone kindly tell me why two results are different and is there any method better to compare Object with Long ?
If it's a meaningful question you think, let's talk about it. Thanks.
Long and Integer are different types. you compared objects of different types.
100 is int. So it is boxed to Integer. So obj and i_num can be compared.
Its preety straight forward -
Object obj = 100;
This 100 is an integer and Object obj hold that integer reference, you can make sure by System.out.println(obj.getClass()); which prints class java.lang.Integer. And It is a example of auto boxing -
System.out.println(((Long)obj) == l_num);
(Long)Obj throws the ClassCastException as it is trying to cast Integer object to Long object which is invalid.
write form would be -
System.out.println(((Long)((Integer)obj).longValue()) == l_num); // it return true
The title is pretty self-explanatory. I'm moving from C# to Java. I have an object and a getter method which returns its ID. I want to compare the ids of two objects of the same type and check if the values of their ids are equal.
tried:
obj.getId() == obj1.getId();
Long id1 = obj.getId();
Long id2 = obj1.getId();
assertTrue(id1.equals(id2))
assertTrue(id1== id2)
In java:
the == operator tells you if the two operands are the same object (instance).
the .equals() method on Long tells you if they are equal in value.
But you shouldn't do either. The correct way to do it is this:
assertEquals(id1, id2);
With assertEquals(), if the assertion fails, the error message will tell you what the two values were, eg expected 2, but was 5 etc
To compare two primitive long you can simply use ==
Example:
long x = 1L;
long y = 1L;
if (x == y) {
System.out.println("value of x and y are same");
}
To compare two Long objects you can use Long.compare(long x, long y). This method was added in java 1.7. Below is the method implementation:
public static int compare(long x, long y) {
return (x < y) ? -1 : ((x == y) ? 0 : 1);
}
Example:
Long x = new Long(1);
Long y = new Long(1);
if (Long.compare(x,y) == 0) {
System.out.println(values of x and y are same);
}
in java,
use == to compare primitives and x.equals(y) to compare objects.
I'm not sure what your question is-- it looks like you tried both, and did neither work?
Note, you are using Long instead of long, so you want to use .equals()
(long is a primitive, Long is an object)
Try doing the following:
assertTrue(id1.longValue() == id2.longValue())
They must not be equal using ==. Use either:
id1.equals(id2)
or
id1.longValue() == id2.longValue()
In both cases I left out null-checks because I doubt you'd forget them, if they were needed here ;)
So, why is Long not always == another Long with the same value? The answer is easy. They're different objects! Depending on how the Long was retrieved they might be the same, because of internal caching. See Long.valueOf.
In addition to all the comments about the right comparison, strong typing can help you resolve your issue.
Does getID() return something of type Long (that's a class type) or of type long (that's a primitive type)? The problem is that if the method returns a primitive value, then comparing with '==' and 'equals()' will both work, because Java automatically casts primitives into wrapper objects when you need them.
But the other way, if getID() returns a Long value, comparing with '==' is likely to fail, because that checks if you have the same object, not if the objects have the same value.
You need to be aware of the difference between Long and long - long is the primitive type, Long is the wrapper type. (A bit like a boxed value in C#, but strongly typed.) What's the return type of getId()?
Simply:
assertEqual(id1, id2);
should be fine if you're doing this in a test. Otherwise, you could use:
if (id1.equals(ids2))
if they're definitely not null, or use Guava:
if (Objects.equal(id1, id2))
to handle nullity. (You can write Objects.equal yourself, of course, but you should definitely get hold of Guava anyway, so you might as well use that...)
It's worth noting that certain wrapper objects are reused - so for example:
// This will work
Long x = 5L;
Long y = 5L;
assertTrue(x == y); // Reference comparison
// This *probably* won't but it could!
x = 10000L;
y = 10000L;
assertTrue(x == y); // Reference comparison
Why does the code below return false for long3 == long2 comparison even though it's literal.
public class Strings {
public static void main(String[] args) {
Long long1 = 256L + 256L;
Long long2 = 512L;
Long long3 = 512L;
System.out.println(long3 == long2);
System.out.println(long1.equals(long2));
}
}
Long is an object, not a primitive. By using == you're comparing the reference values.
You need to do:
if(str.equals(str2))
As you do in your second comparison.
Edit: I get it ... you are thinking that other objects act like String literals. They don't*. And even then, you never want to use == with String literals either.
(*Autobox types do implement the flyweight pattern, but only for values -128 -> 127. If you made your Long equal to 50 you would indeed have two references to the same flyweight object. And again, never use == to compare them. )
Edit to add: This is specifically stated in the Java Language Specification, Section 5.1.7:
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.
Note that long is not specifically mentioned but the current Oracle and OpenJDK implementations do so (1.6 and 1.7), which is yet another reason to never use ==
Long l = 5L;
Long l2 = 5L;
System.out.println(l == l2);
l = 5000L;
l2 = 5000L;
System.out.println(l == l2);
Outputs:
true
false
You could also get the primitive value out of the Long object using:
str.longValue()
If you want to do
str3==str2
do like this..
str3.longValue()==str2.longValue()
This serves your purpose and much faster because you are comparing two primitive type values not objects.
Here Long is a Wrapper class so the below line will compare the reference not the content.
long3 == long2
its always better to compare with ** .longValue() ** like below
long3.longValue() == long2.longValue()
If we use in-build equal() method that also will do the same thing with null check.
long3.equals(long2)
Below is the internal implementation of equals() in java
public boolean equals(Object obj) {
if (obj instanceof Long) {
return value == ((Long)obj).longValue();
}
return false;
}
Let's first consider the following expressions in Java.
Integer temp = new Integer(1);
System.out.println(temp.equals(1));
if(temp.equals(1))
{
System.out.println("The if block executed.");
}
These all statements work just fine. There is no question about it. The expression temp.equals(1) is evaluated to true as expected and the only statement within the if block is executed consequently.
Now, when I change the data type from Integer to Long, the statement temp1.equals(1) is unexpectedly evaluated to false as follows.
Long temp1 = new Long(1);
System.out.println(temp1.equals(1));
if(temp1.equals(1))
{
System.out.println("The if block executed.");
}
These are the equivalent statements to those mentioned in the preceding snippet just the data type has been changed and they behave exactly opposite.
The expression temp1.equals(1) is evaluated to false and consequently, the only statement within the if block is not executed which the reverse of the preceding statements. How?
You're comparing a Long to an int. The javadoc for java.lang.Long#equals says that the equals method
Compares this object to the specified object. The result is true if and only if the argument is not null and is a Long object that contains the same long value as this object.
Instead try System.out.println(new Long(1).equals(1L)); Now that you're comparing a Long to a Long instead of a Long to an Integer, it will print true.
The reason you can do that comparison is because of autoboxing in Java.
The actual method you are calling is this:
http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/Long.html#equals(java.lang.Object)
which is comparing your Long object to some other Object, not to an actual primitive int.
What happens when you call the method is that your primitive integer(1) is being autoboxed into an Object(Integer) so then you are effectively calling:
new Long(1).equals(new Integer(1));
which is why it fails.
This is why if you call
new Long(1).equals(1L)
this would work, because Java will autobox the 1L (primitive long, not int) into a Long object, not an Integer object.
The literal value 1 is not a long, it's an int. Try the above code with this instead:
System.out.println(temp1.equals(1L));
And
if (temp1.equals(1L))
As you can see, putting an L after the literal value 1 indicates that it's a long, and then the comparisons work as expected.
Java is being lazy.
When you perform the following comparison java will automatically cast the int to a long (as a long can contain any value an int can contain). And the comparison is between two longs and not two ints.
int i = 1;
long l = 1L;
boolean b = i == l;
Java is able to do this because the type information about i and l is known at compile time and when performing the comparison. However, when you use the boxed version the type can be known at compile time, but not when performing the comparison. This is because the comparison has to done within an equals method, and since equals takes Object as a parameter the type information is lost. Thus Java is lazy and only checks to see if two boxed numbers are equal if they are both of instances of same Number class (eg. both Integer, or both Long, or both Double, etc...).
Turns out the only fully reliable way to compare two numbers of unknown type at runtime is to convert both to strings and both to BigDecimal and then to use the method compareTo (and not equals). Though if you know you are only ever going to get longs and ints then life is simpler as you can just do the following.
Number n0 = new Long(1L);
Number n1 = new Integer(1);
boolean equal = n0.longValue() == n1.longValue();
According to Javadoc's page on Long, the .equals method evaluates to true only if
The argument is a Long object
If (1) is true, then the Long objects must have equal values
In your scenario, 1 is an int, not a Long object, so it fails (1), and therefore, evaluates to false. If you need to test to a long, use 1L instead.
That behaviour is consistent with autoboxing converting the 1 to an Integer which then compares equal to another Integer(1). Comparing a Long to an Integer yields false.
If you would use 1L to compare against Long it would yield true.
Long temp1 = new Long(1); System.out.println(temp1.equals(1));
if(temp1.equals(1)) {
System.out.println("The if block executed."); }
in this code temp1.equals(1) is comparing a Long object to Integer object which gives the result false ,we can correct it by using 1L instead of 1 ,,,eg temp1.equals(1L), by doing this we are comparing Long object with a Long and gives result TRUE
The implementation of equals() method of class Long illustrates why:
public boolean equals(Object obj) {
if (obj instanceof Long) {
return value == ((Long)obj).longValue();
}
return false;
}
The equals method in Java.lang.Long initially starts with an instanceOf Long check only after that the value is compared.
public boolean equals(Object obj) {
if (obj instanceof Long) {
return value == ((Long)obj).longValue();
}
return false;
}
So if you are going to use and Integer Value int the place of a Long value then the first check fails and hence you will get false as the result .
You can compare Long/integer values without uting equals(). This is only needed when you are comparing strings as far as I know.