I was wondering if java automatically turns a Integer into an int when comparing to an int? Or will the == try and compare references on primitives?
Is this always true or do I need to do i.intValue()==2?
Integer i = Integer.valueOf(2);
if (i==2){
//always?
}
Yes, when comparing int using == arguments will be unboxed if necessary.
Relevant section from the Java Language Specification:
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). If the promoted type of the operands is int or long, then an integer equality test is performed; if the promoted type is float or double, then a floating-point equality test is performed.
Note that binary numeric promotion performs value set conversion (§5.1.13) and unboxing conversion (§5.1.8). Comparison is carried out accurately on floating-point values, no matter what value sets their representing values were drawn from.
Same applies for <, <=, >, >= etc, as well as +, -, * and so on.
So,
System.out.println(Integer.valueOf(17) == 17);
prints true :-)
but you can compare two equal strings with == and sometimes get true or fals depending on how the strings were pooled...
Right, and there is actually a similar situation for Integers as well.
When boxing (transforming int to Integer) the compiler uses a cache for small values (-128 - 127) and reuses the same objects for the same values, so perhaps a bit surprising, we have the following:
System.out.println(Integer.valueOf(100) == Integer.valueOf(100)); // prints true
System.out.println(Integer.valueOf(200) == Integer.valueOf(200)); // prints false
Yes, it will unbox. This is covered in section 15.21.1 of the JLS (the numeric == operator):
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). If the promoted type of the operands is int or long, then an integer equality test is performed; if the promoted type is float or double, then a floating-point equality test is performed.
Note that binary numeric promotion performs value set conversion (§5.1.13) and unboxing conversion (§5.1.8).
(I've linkified section 5.1.8 as that's what talks about the conversion from Integer to int being available.)
This is possible.
That Java-feature is called Autoboxing.
yes, it's automatically converted.
you can also do
Integer i = 2;
Yes this works because auto (un)boxing.
It will compare primitives - the Integer will be unboxed. But as a rule of thumb: avoid that. Always prefer primitives, and be careful when comparing objects with ==
Apart from seeing this in the JLS, here's how you can verify that:
Instead of Integer.valueOf(2), which uses a cache, use new Integer(2). This is guaranteed to be a different instance than the one that will be obtained if 2 if boxed (the boxing happens with Integer.valueOf(..)). In this case, the condition is still true, which means that it's not references that are compared.
Related
In Java when I print something like this
System.out.println(1.0f*1l));
I get an output of
1.0
or with
System.out.println(((byte)1)*'A');
I get an output of
65
In both cases, one of the types is bigger than the other. Longs are 64-bits while floats are 32-bits, and bytes are 8-bits while chars are 16-bits. Despite this, Java outputs the result in the smaller type. Wouldn't this be considered a loss of precision?
Java Language Specification provides a list of rules governing the type of result based on the types of operands.
In particular, section 4.2.4 says that
If at least one of the operands to a binary operator is of floating-point type, then the operation is a floating-point operation, even if the other is integral.
which explains why float "wins" against a long.
Integer arithmetic is explained in section 5.6.2. Specifically, it says that
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.
• Otherwise, if either operand is of type float, the other is converted to float.
• Otherwise, if either operand is of type long, the other is converted to long.
• Otherwise, both operands are converted to type int.
That is why in your second example the result, 65, is of type int.
Java widens type based on the range of possible values. This means float is considered wider thanlong.
Also integer operations which are not long are performed as int.
A byte * char is an int
You are asking about Binary Numeric Promotion (JLS 5.6.2) (emphasis mine):
When an operator applies binary numeric promotion to a pair of operands, each of which must denote a value that is convertible to a numeric type, the following rules apply, in order:
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.
Otherwise, if either operand is of type float, the other is converted to float.
Otherwise, if either operand is of type long, the other is converted to long.
Otherwise, both operands are converted to type int.
The expression 1.0f*1l is a float and long, so the long is converted to a float.
The expression ((byte)1)*'A' is a byte and a char, so they are both converted to int.
In addition to the other answers that spell out the rules in detail, I think it's also worth considering why it should be this way. Suppose you do
2.7F * 2L
The true mathematical answer to this multiplication is 5.4. Therefore if the answer were a long, it would have to be 5L (5 is the closest integer to 5.4). Because of this kind of thing it makes much more sense for the result of multiplying a floating-point value by an integer to be a floating point value. I think there would be many more questions about this on Stack Overflow if the following line of code printed 5.
System.out.println(2.7F * 2L);
In fact it prints 5.4.
It also makes sense that all operations between integer types (except long) are done with int. After all, a byte is usually thought of as a small packet of data, and a char is usually thought of as a character. From these perspectives multiplying byte or char values isn't really meaningful. It makes much more sense to keep the rules simple and just do the operations with int.
This question already has an answer here:
Why byte and short values are promoted to int when an expression is evaluated [duplicate]
(1 answer)
Closed 7 years ago.
When we do addition,subtractions,divide(etc..)in byte short data types the result is coming from int value...why is that...?
e.g:- in above code does not compile because the result in c is coming from int why is that happen...??? when we try to print c using system out it came error because result is in int
public class A {
public static void main(String[] args) {
byte a = 12;
byte b = 10;
byte c = a + b;
System.out.println(c);
}
}
According to java doc the when we perform operations on two bytes there is probability that the output would be a number which can't be handled by byte, so it was decided by creators of java to auto cast it to Integer. So it's like this.
This is well answered here, starting from an identical scenario :) http://www.coderanch.com/t/499127/java/java/Adding-bytes
To quote http://java.sun.com/docs/books/jls/third_edition/html/conversions.html#5.6.2
When an operator applies binary numeric promotion to a pair of operands, each of which must denote a value that is convertible to a numeric type, the following rules apply, in order, using widening conversion (§5.1.2) to convert operands as necessary:
If any of the operands is of a reference type, unboxing conversion (§5.1.8) is performed. Then:
If either operand is of type double, the other is converted to double.
Otherwise, if either operand is of type float, the other is converted to float.
Otherwise, if either operand is of type long, the other is converted to long.
Otherwise, both operands are converted to type int.
The spec says:
https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.18.2
The binary + operator performs addition when applied to two operands of numeric type, producing the sum of the operands.
The binary - operator performs subtraction, producing the difference of two numeric operands.
Binary numeric promotion is performed on the operands (§5.6.2).
Note that binary numeric promotion performs value set conversion (§5.1.13) and may perform unboxing conversion (§5.1.8).
The type of an additive expression on numeric operands is the promoted type of its operands.
https://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.6.2
When an operator applies binary numeric promotion to a pair of operands, each of which must denote a value that is convertible to a numeric type, the following rules apply, in order:
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.
Otherwise, if either operand is of type float, the other is converted to float.
Otherwise, if either operand is of type long, the other is converted to long.
Otherwise, both operands are converted to type int.
If you combine the two you see that any operand in an addition will be promoted to either int or long and any primitive smaller than int will be promoted to int. The result of the operation is the type of both operands - which it int.
The reasoning behind that is most probably that int is the most common datatype which reduces probability of overflow while not requiring as much space as a long. The space argument probably isn't as generally valid as it used to be anymore but that part of the spec was defined like in 1995 and an inherent part of the language (which you can't change without breaking compatibility).
Any Binary arithmetic operations we performed on char & byte datatype(and short) promote it to int.
For more details please refer JLS 5.6.2.
This works:
final byte a = 12;
final byte b = 10;
byte c = a + b;
Or this:
byte a = 12;
byte b = 10;
byte c = (byte)( a + b);
Can you please run the below and explain?
Object o = true ? new Integer(1) : new Double(2.0);
System.out.println(o);
I found that surprising as someone would expect 1 to be printed and not 1.0
It's not a surprise at all, although it might seem like one. The behaviour is specified in JLS §15.25 - Conditional Operator:
Otherwise, if the second and third operands have types that are
convertible (§5.1.8) to numeric types, then there are several cases:
If one of the operands is of type byte or Byte and the other is of
type short or Short, then the type of the conditional expression is
short.
[...]
Otherwise, binary numeric promotion (§5.6.2) is applied to the operand
types, and the type of the conditional expression is the promoted type
of the second and third operands.
Note that binary numeric promotion performs value set conversion (§5.1.13) and may perform unboxing conversion (§5.1.8).
So the Integer and Double types are unboxed to their respective primitive counterparts - int and double, as a process of binary numeric promotion. And then the type of the conditional operator is the promoted type of int and double, which is double. Hence the result is 1.0. And of course the final result is then boxed back to Double.
Here is an article published in DZone yesterday talking about it:
Java auto unboxing gotcha
Funny enough, the example code looks similar...
I have been told to never use == for strings but for everything else because .equals would compare the values rather than the instances of the object. (Which I understand the difference of).
According to some sites, == compares memory locations?
What I don't understand is if you're comparing an integer with another, why would it compare memory locations, or is this just for strings?
If you're comparing int 3 to int 4 obviously it wouldn't be in the same memory location, but then if you're comparing int 4 to int 4, does that mean all integers with the value of 4 is stored in the same memory location?
According to some sites, == compares memory locations?
The expression a == b compares the content of a and b, regardless of their types.
What I don't understand is if you're comparing an integer with another, why would it compare memory locations, or is this just for strings?
In case a and b are references, the == operator will compare "memory locations" since that is what the variables contain.
In case a and b are of primitive types, such as int or double the variables will contain actual values, consequently these values (and not their locations) will be compared.
(Note that a variable can never contain an object such as a String, it can at most point at an object.)
Does that mean all integers with the value of 4 is stored in the same memory location?
No. As explained above, ints are compared "directly". When it comes to Integer the story is slightly different. First of all new guarantees that you get hold of a fresh reference, that is
Object i = new Integer(5);
Object j = new Integer(5);
... i == j ...
will always yield false.
If you go through auto-boxing however:
Object i = (Integer) 5;
Object j = (Integer) 5;
... i == j ...
you'll get true due to the fact that auto-boxing goes through a cache for values in the range -128-127. (See for instance this question: Compare two Integer: why is == true?)
== compares the values of the oparands whether it is primitive or reference type.
If the operands are primitive the values of the operands will be compared.
Operands which are references contains values i.e. address to access the object they are referring to. String are not primitive data type, they are considered as objects in java, When you are comparing two references of type string, the result will be true only when the values of the operands i.e. address of the String objects are equal ( which means they refer to the same String object).
Simply put: the thing is that int is a primitive type whereas String is an object. The values of primitive types can be compared with == since the variable points to the value itself rather than the reference to the value.
int's are primitive types in java and as such they don't represent an object "reference" but the value directly.
== compares reference types. int is a primitive type.
so:
int x = 3;
int y = 3;
x==y is true
but using the Integer reference type
Integer x = new Integer(3);
Integer y = new Integer(3);
x == y is false
The == operator compares the references of objects in memory and Strings are objects - primitives aren't objects so as long as they are of the same type, then == will work. As you say, if they are the object variants of primitives (e.g. Integer for int) then java (>5) autoboxes in order to do the compare.
From the Java Specification 15.21 Equality Operators:
15.21 Equality Operators
The equality operators are syntactically left-associative (they group
left-to-right), but this fact is essentially never useful; for
example, a==b==c parses as (a==b)==c. The result type of a==b is
always boolean, and c must therefore be of type boolean or a
compile-time error occurs. Thus, a==b==c does not test to see whether
a, b, and c are all equal.
EqualityExpression:
RelationalExpression
EqualityExpression == RelationalExpression
EqualityExpression != RelationalExpression The == (equal to) and the!= (not equal to) operators are analogous to the relational
operators except for their lower precedence. Thus, a
In all cases, a!=b produces the same result as !(a==b). The equality
operators are commutative if the operand expressions have no side
effects.
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). If the promoted type of the operands is int or long, then an
integer equality test is performed; if the promoted type is float or
double, then a floating-point equality test is performed. Note that
binary numeric promotion performs value set conversion (§5.1.13) and
unboxing conversion (§5.1.8). Comparison is carried out accurately on
floating-point values, no matter what value sets their representing
values were drawn from.
Floating-point equality testing is performed in accordance with the
rules of the IEEE 754 standard:
If either operand is NaN, then the result of == is false but the
result of != is true. Indeed, the test x!=x is true if and only if the
value of x is NaN. (The methods Float.isNaN and Double.isNaN may also
be used to test whether a value is NaN.) Positive zero and negative
zero are considered equal. Therefore, -0.0==0.0 is true, for example.
Otherwise, two distinct floating-point values are considered unequal
by the equality operators. In particular, there is one value
representing positive infinity and one value representing negative
infinity; each compares equal only to itself, and each compares
unequal to all other values. Subject to these considerations for
floating-point numbers, the following rules then hold for integer
operands or for floating-point operands other than NaN: The value
produced by the == operator is true if the value of the left-hand
operand is equal to the value of the right-hand operand; otherwise,
the result is false. The value produced by the != operator is true if
the value of the left-hand operand is not equal to the value of the
right-hand operand; otherwise, the result is false.
15.21.2 Boolean Equality Operators == and !=
If the operands of an equality operator are both of type boolean, or
if one operand is of type boolean and the other is of type Boolean,
then the operation is boolean equality. The boolean equality operators
are associative. If one of the operands is of type Boolean it is
subjected to unboxing conversion (§5.1.8).
The result of == is true if the operands (after any required unboxing
conversion) are both true or both false; otherwise, the result is
false.
The result of != is false if the operands are both true or both false;
otherwise, the result is true. Thus != behaves the same as ^
(§15.22.2) when applied to boolean operands.
15.21.3 Reference Equality Operators == and !=
If the operands of an equality operator are both of either reference
type or the null type, then the operation is object equality. A
compile-time error occurs if it is impossible to convert the type of
either operand to the type of the other by a casting conversion
(§5.5). The run-time values of the two operands would necessarily be
unequal.
At run time, the result of == is true if the operand values are both
null or both refer to the same object or array; otherwise, the result
is false.
The result of != is false if the operand values are both null or both
refer to the same object or array; otherwise, the result is true.
While == may be used to compare references of type String, such an
equality test determines whether or not the two operands refer to the
same String object. The result is false if the operands are distinct
String objects, even if they contain the same sequence of characters.
The contents of two strings s and t can be tested for equality by the
method invocation s.equals(t). See also §3.10.5.
The == operator compares ints by value and objects by address. Thus, == is correct for ints but (usually) not for Strings.
Note that if you know that both Strings have been returned by the String.intern method, == works correctly, as intern is guaranteed to return the same address for identical strings.
Objects are equality by value, but the value that objects have is a reference to the memory location. Primitives (i.e. int, boolean, char, double) do not use references, but store their value. So when == is used, it compares the value of the two. In the case of objects it's a reference; however, in the case of primitives it is the value it stores.
Can any one tell what is numeric promotion?
Numeric promotion is the conversion of a smaller numeric type to a larger numeric type, so that integer and floating-point operations may take place. In numerical promotion, byte, char, and short values are converted to int values. The int values are also converted to long values, if necessary. The long and float values are converted to double values, as required.
Numeric Promotion Rules
If two values have different data types, Java will automatically promote one of the values to the larger of the two data types.
If one of the values is integral and the other is floating-point, Java will automatically promote the integral value to the floating-point value’s data type.
Smaller data types, namely byte, short, and char, are first promoted to int any time they’re used with a Java binary arithmetic operator, even if neither of the operands is int.
After all promotion has occurred and the operands have the same data type, the resulting value will have the same data type as its promoted operands
Numeric promotion is a conversion of an operand (at least one of the numbers involved) to a common type.
For example:
int i = 10;
double d1 = 2.5;
double d2 = d1 * i;
In this case, i is promoted to double so the calculation can be performed. In some ways, you can think of this is analogous to boxing, but boxing involves moving from a struct to an object (from the stack to the heap). But, using the analogy does give an idea of the fact the integral value is being made into a floating point to perform the calculation.
If you look here, you will see the following quote:
Numeric promotion (§5.6) brings the
operands of a numeric operator to a
common type so that an operation can
be performed.
They are referencing this section, where they give a variety of examples. The classic example is that of an int times a float. The integer is promoted to a float so that the multiplied result is, therefore, a float.