I suppose that conversions described in jls are sorted according the priority.
first has greate priority.
jls
Thus I solved that Boxing has greater priority than Unboxing. I decided to check this assumption.
research following code:
public class BoxingUnboxingPriority {
public static void main(String [] args){
int sn = 1000;
Integer isn1= new Integer(sn);
System.out.println(sn == isn1 );
}
}
out:
true
What is boxing? is just new Integer(primitiveInt)
I changed the code a bit
int sn = 1000;
Integer isn1= new Integer(sn);
Integer isn2= new Integer(sn);
System.out.println(isn1 == isn2 );
out:
false
Thus I made mistake.
Please clarify me this issue.
The relevant section:
15.21.1. Numerical Equality Operators == and !=
If the operands of an equality operator are both of numeric type, or one is of numeric type and the other is convertible (§5.1.8) to numeric type, binary numeric promotion is performed on the operands (§5.6.2).
So:
Integer o = 1;
int i = 1;
boolean b = o == i;
...is equivalent to:
boolean b = o.intValue() == i;
Where both are of type Integer neither is a primitive numeric type - they are both object references.
When you use primitive with a Wrapper object, that wrapper object will be unboxed and then the operation will be applied.
In your first case, when you comparing sn with isn1, isn1 will be unboxed and the value will be compared. So you got true.
In second case, isn1, isn2 are two different object, so == operator will give false
I suppose that conversions described in jls are sorted according the priority.
That is incorrect. The JLS does not talk about "priorities" for conversions. It is not a recognized concept.
In fact, the conversions that can be applied are documented on a case by case basis for each operator, and so on. Thus JLS 15.21.1 says that == or != for numeric types results in "binary numeric promotion" of both operands. And JLS 5.6.2 says that binary numeric promotion consists of "unboxing conversion" (5.1.8) followed by "widening primitive conversion" (5.1.2) and finally "value set conversion" (5.1.3).
By contrast, JLS 15.21.3 says that when two references are compared using == or !=, no promotions or conversions take place.
(In fact, a common Java beginners mistake is to use == to compare two Integer objects rather than the equals(Object) method. And probably that is what "the question" you are looking at is trying to test your understanding of ...)
int sn=1000;
Integer isn1=new Integer(sn);
System.out.println(sn == isn1 );
will be converted to
System.out.println(sn == isn1.intValue());
while comparing primitive with wrapper the wrapper object first will be unboxed and then comparison.
wrapper object intValue() returns int so due to primitive comparison result true.
Integer isn1= new Integer(sn);
Integer isn2= new Integer(sn);
System.out.println(isn1 == isn2 );
// comparing two different object so false.
Related
As the String is an object, you need to use the string.equals(string) method to confirm that the two strings are equal.
However, why do you use the == to check if two chars are equal, char1 == char2, rather than char1.equals(char2)?
Perhaps, this will help to understand the difference on == vs equals.
#Test
public void testCharacterEquals() {
//primitive type uses == operator for equals comparasion
char a1 = 'A';
char a2 = 'A';
if (a1 == a2) {
System.out.println("primitive type comparasion: it's equal");
}
//From Java doc; The Character class wraps a value of the primitive type char in an object. An object of type Character contains a single field whose type is char.
//Object type uses equals method for equals comparasion
Character character1 = 'A';
Character character2 = 'A';
if (character1.equals(character2)) {
System.out.println("object type comparasion: it's equal");
}
}
It depends on using a primitive type, char, int, etc. And using Objects like String. A primitive type like an int can be compared 1 == 1 and if you check 2 objects to each other ObjectA != ObjectB.
Check out this answer over here: Primitive vs Object type in Java
Or over here: https://chortle.ccsu.edu/java5/Notes/chap09C/ch09C_2.html
Quote:
A primitive data type uses a small amount of memory to represent a
single item of data. All data of the same primitive type are the same
size.
For example, primitive type int represents integers using 32 bits. All
variables of type int use 32 bits.
There are only eight primitive data types in Java: byte, short, int,
long, float, double, char, and boolean. A Java program cannot define
any other primitive data types.
An object is a large chunk of memory that can potentially contain a
great deal of data along with methods (little programs) to process
that data. There are thousands of object classes that come standard
with Java, and a programmer can easily create additional classes.
(Although there are thousands of standard classes, for this course you
only need become familiar with a dozen or so classes.)
Where 2 strings are 2 different objects. Therefor not the same object and not the same string. While the characters might be the same.
Basically Java has primitive types (int, char, short, long, byte ....)
and Reference Data types/ Objects composed of other primitives and Objects.
equals() is a method of all Java Objects. But char is not an Object type in Java, it is a primitive type, it does not have any method or properties, so to check equality they can just use the == equals operator.
You can also use a comparator if you want.
public static boolean compareChars(char c1, char c2){
int comp = Character.compare(c1, c2);
if(comp>0){
return false;
}else{
return true;
}
}
public static void main (){
boolean b1 = compareChars('A', 'A') //return true;
boolean b2 = compareChars('A', 'C') //return false;
}
Because char is a primitive type and does not implement equals, == compares char values directly in this case, where as String is an object. So for object comparison, the equality operator is applied to the references to the objects, not the objects they point to. Two references are equal if and only if they point to the same object, or both point to null.
If you want to compare strings (to see if they contain the same characters), you need to compare the strings using equals().
Hence, the operator == checks equality of values on primitive types, but it checks references equality for objects. If the two objects are referenced by equal references, a reference and an object are different in Java.
System.out.println(" answer is " + (5.0==5L));
This returns true!
It should return a false value because two different types are being compared.
Even though the double is compared to a long value!
The two operands are going through binary numeric promotion as per JLS section 5.6.2 in order to get to a single type for both operands.
The rules are like this:
If any operand is of a reference type, it is subjected to unboxing conversion (§5.1.8).
Widening primitive conversion (§5.1.2) is applied to convert either or both operands as specified by the following rules:
If either operand is of type double, the other is converted to double.
...
...
Your second operand is of type double, so the long value is implicitly converted to double, then the two double values are compared - and they're equal.
When comparing longs to doubles, the long is promoted to a double, and then the two are compared. Since both are equal to five, the result is true.
It returns true because it is comparing two types of "primitive variables". And if they are the same value, it works.
In comparison, using "==" on "object variables" returns true if the reference is to the same object, for example
Object a = new Object();
Object b = a;
//then a==b is true
But:
Object a = new Object();
Object b = new Object();
//then a==b is false
This question already has answers here:
How can I properly compare two Integers in Java?
(10 answers)
Closed 5 years ago.
I have the following code:
public class Test {
public static void main(String[] args) {
Integer alpha = new Integer(1);
Integer foo = new Integer(1);
if(alpha == foo) {
System.out.println("1. true");
}
if(alpha.equals(foo)) {
System.out.println("2. true");
}
}
}
The output is as follows:
2. true
However changing the type of an Integer object to int will produce a different output, for example:
public class Test {
public static void main(String[] args) {
Integer alpha = new Integer(1);
int foo = 1;
if(alpha == foo) {
System.out.println("1. true");
}
if(alpha.equals(foo)) {
System.out.println("2. true");
}
}
}
The new output:
1. true
2. true
How can this be so? Why doesn't the first example code output 1. true?
For reference types, == checks whether the references are equal, i.e. whether they point to the same object.
For primitive types, == checks whether the values are equal.
java.lang.Integer is a reference type. int is a primitive type.
Edit: If one operand is of primitive type, and the other of a reference type that unboxes to a suitable primitive type, == will compare values, not references.
Integer objects are objects. This sounds logical, but is the answer to the question. Objects are made in Java using the new keyword, and then stored in the memory. When comparing, you compare the memory locations of the objects, not the value/properties of the objects.
Using the .equals() method, you actually compare the values/properties of objects, not their location in memory:
new Integer(1) == new Integer(1) returns false, while new Integer(1).equals(new Integer(1)) returns true.
ints are a primitive type of java. When you create an int, all that is referenced is the value. When you compare any primitive type in Java, all that is compared is the value, not the memory location. That is why 5 == 5 always returns true.
When you compare an Integer object to a primitive type, the object is cast to the primitive type, if possible. With an Integer and an int this is possible, so they are compared. That is why Integer(1).equals(1) returns true.
What you'll use new Integer(1) to create new object, it creates a totally different object each time even though it has the same value. The '==' checks if the objects are same, not data values. In your case, you could have checked the value as follows :
if(alpha.intValue() == foo.intValue()) {
//
}
Integer == int here auto boxing applied ( so Integer converted to int before comparision) so true.. but Integer == Integer here object comparison so as reference are different so false..
First example:
Using the == operator between objects checks for reference equality, and since you are comparing two different objects they do not equal.
Second example:
When using the == between a wrapper type (Integer, Long, etc.) and a numeric type (int, long, etc.) the wrapper type is unboxed and the equality check is done between the two primitive numeric types (I.e. between int and int). The unboxing is part of binary numeric promotion, read more here: http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.6.2
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.