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.
Related
I am confused on a few things regarding using double.
If i were to initialize 2 doubles with the same literal, would == always evaluate to true? for example, if following outputs true but i don't know if this is by chance:
double a = .1d;
double b = .1d;
System.out.println(a==b);
I get the same result when using Double instead of double:
Double a = .1d;
Double b = .1d;
System.out.println(a.equals(b));
According to Double documentation, equals() return true if doubleValue() are equal.
So the question is, is "==" for double and "equals()" for Double guaranteed to evaluate to true for 2 variables initialized using the same literal?
When would they evaluate to false? Is this when arithmetic operations are involved?
Thanks
In general == is an operator which checks for equality. Object variables are references so it checks for reference or address equality. In the case of primitive data types representing values in the memory that also means that it checks for value equality.
The method equals(~) checks for value or content equality. You do not use it for primitive data types but for Objects.
That is also the case for double and Double. The problem which is arising with doubles is the mismatch of the values induced by rounding errors.
Some arithmetic operations may handle rounding differently so you might get false for value equality even if you think it should be equal.
It should be stated that even if the rounding rules are a bit inconsistent arithmetic operations are deterministic so that inconsistency can be handled.
This question already has answers here:
Why does the ternary operator unexpectedly cast integers?
(3 answers)
Closed 7 years ago.
I had this piece of code in my application (simplified version):
Object result;
if (check)
result = new Integer(1);
else
result = new Double(1.0);
System.out.println(result);
return result;
Then I decided to refactor the if-else statement to a ternary conditional expression so my code is more concise:
Object result = check ? new Integer(1) : new Double(1.0);
System.out.println(result);
return result;
It turned out that in case check is true the two versions print different results:
1
or:
1.0
Isn't the ternary conditional equivalent to the corresponding if-else?
The if/else and the conditional (ternary) expression are not quite equivalent. The result of the conditional expression must have a type.
You're observing the effects of numeric type promotion (or type coercion).
Here's an excerpt from the language spec (see here), from the section describing the return value of the conditional expression:
Otherwise, if the second and third operands have types that are convertible (§5.1.8) to numeric types, then there are several cases:
The final such case is (I've omitted the other cases here):
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.
Here's the additional spec related to binary numeric promotion:
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.
It's the first case (following cases omitted). double always wins.
So regardless of the order of the 2nd and 3rd operands in your conditional expression, the return type of the expression will be promoted to double.
Put simply, the ternary operator isn't different from other operators where numeric type promotion is concerned.
When you have something like System.out.println(1 + 1.0), you expect it to print 2.0, because the operands used in the output are subject to numeric type promotions.
It's exactly the same with the ternary operator: System.out.println(true ? 1 : 1.0) will print 1.0 after doing the same numeric type promotions it would have done if the expression was 1 + 1.0.
It works that way for a very simple reason: the type of the operator's result should be known at compile-time, while its actual result is determined at run-time.
Short answer
The first example explicitly typed as Object, which causes an upcast.
The second example is implicitly typed as Double, which causes numeric widening.
Long answer
In the example with Object, there is no conversion of values, just an upcast, and 1 is printed.
Object result;
if (1 == 1)
result = new Integer(1);
else
result = new Double(1.0);
If you instead declared using Double, it would be a widening and print 1.0.
Double result;
if (1 == 1)
result = new Integer(1);
else
result = new Double(1.0);
These are rather straightforward since there is an explicit type.
The ternary expression, however, has no explicit type, and the rules are non-trivial.
The type of a conditional expression is determined as follows:
If the second and third operands have the same type (which may be the null type), then that is the type of the conditional expression.
If one of the second and third operands is of primitive type T, and the type of the other is the result of applying boxing conversion (§5.1.7) to T, then the type of the conditional expression is T.
If one of the second and third operands is of the null type and the type of the other is a reference type, then the type of the conditional expression is that reference type.
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.
If one of the operands is of type T where T is byte, short, or char, and the other operand is a constant expression (§15.28) of type int whose value is representable in type T, then the type of the conditional expression is T.
If one of the operands is of type T, where T is Byte, Short, or Character, and the other operand is a constant expression (§15.28) of type int whose value is representable in the type U which is the result of applying unboxing conversion to T, then the type of the conditional expression is U.
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).
Otherwise, the second and third operands are of types S1 and S2 respectively. Let T1 be the type that results from applying boxing conversion to S1, and let T2 be the type that results from applying boxing conversion to S2. The type of the conditional expression is the result of applying capture conversion (§5.1.10) to lub(T1, T2) (§15.12.2.7).
http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.25
The "promoted type" of numerics Integer and Double is Double.
In addition to #pb2q answer
you can verify it as
public class test {
public static void main(String[] args) {
Object result;
Boolean check = true;
if (check)
result = new Integer(1);
else
result = new Double(1.0);
System.out.println(result);
result = check ? new Integer(2) : new Double(1.0);
System.out.println(result);
}
}
it will print 2.0 instead of 2 because of numeric promotion
In addition to the existing answers, you can avoid the problem by specific casting to the type you want:
Object result = args.length < 100 ? (Object)2 : (Object)1.0;
Casting to Object boxes the integer as an Integer, and the double as a Double. The expressions on either side of the ":" are then both of type Object, so the compiler does not need to generate any further conversions.
I have found quote from jls:
The equality operators may be used to compare two operands that are
convertible (§5.1.8) to numeric type, or two operands of type boolean
or Boolean, or two operands that are each of either reference type or
the null type. All other cases result in a compile-time error.
But this code
String str= "";
Number num = 1;
System.out.println(str == num);
every operand is reference!
said that it is incompatible types.
Where did in jls say that these types should be compatible ?
In section 15.21.3 (Reference Equality Operators == and !=):
It is a compile-time error 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.
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.
even = number % 2 == 0;
This is a valid java assignment which was given in a website as example.
So does equality operator return a boolean value after evaluation ?
Like in this case, number % 2 == 0 , if true, it assigns even = true?
Yes. Comparison operators evaluate to boolean values.
Yes. From the Java Language Specification, section 15.21:
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.
(Emphasis mine - the rest of the paragraph is somewhat irrelevant, but it's the context in which the important phrase appears.)
Yes, comparisons made with boolean operators evaluate to a boolean value