Ever tried running this on your ENTERPRISE VIRTUAL MACHINE? Integer a = 1000;
Integer b = 1000;
System.out.println("a == b (1000 == 1000): " + (a == b));
Integer aa = 100;
Integer bb = 100;
System.out.println("aa == bb (100 == 100): " + (aa == bb));
Guess what's the output, run it and report back.
after fixing those errors:
expected output: a == b (1000 == 1000): false
aa == bb (100 == 100): false
actual output: a == b (1000 == 1000): false
aa == bb (100 == 100): true
Name:
Anonymous2010-05-17 20:14
As is: Needs libraries and public class frame
With necessary corrections: a == b (1000 == 1000): false
aa == bb (100 == 100): true
But this is not correct because you fudged the object constructor for the wrapper class.
After corrections to the Integer wrapper class (e.g., Integer a = new Integer("1000");): a == b (1000 == 1000): false
aa == bb (100 == 100): false
Essentially your shoddy coding failed, not the language. Good day.
>>4 corrections
comparing objects using the equality operator
Name:
Anonymous2010-05-17 20:30
>>5
It's true that jokes/complaining about the way Java deals with autoboxing are getting old, I don't agree that the hate is misdirected. The way Java does autoboxing is ridiculous, and the fact that it's documented doesn't make it much less so.
Name:
Anonymous2010-05-17 20:32
>>7
Actually the equality operator is crucial.
The point is that [m]aa == bb[m] will be unboxed but a == b won't.
This is not obvious.
Name:
Anonymous2010-05-17 20:39
>>9
There is no unboxing in the OP's example code. I thought that was the point of this exercise. You manually box it and then manually unbox it. And, unless you unbox the primitive from the wrapper, it should return false because Java can not prove that one object is equal to another using the simple boolean comparison.
On the other hand, OP does have an unstated point that, for calling itself an "object-oriented language," Java should have no excuse for object == object not working out somehow.
>>9
Why is that exactly? I've kept clear of Java, so I totally don't get it. Is there any way in which that should make sense?
Name:
Anonymous2010-05-17 20:50
I just ran a test. The essential code is: int i = -1000;
Integer a, b;
for(; i <= 1000; i++)
{
a = i;
b = i;
if(a == b)
{
System.out.println("a == b ("+i+" == "+i+"): " + (a == b));
}
}
The results? -128 to +127 returned true for comparing Integer a and Integer b. In other words, this terrible unboxed comparison, where the wrapper class is fed with a primitive rather than a constructor, is true only for unsigned 8-bit int values. The same might apply for the Float and Double wrapper classes in some way but I am not interested in checking at the moment; maybe later.
Furthermore, there is no auto-unboxing in Java. WYSIWYG
>>9
The equality operator is crucial in the comparison failing- ergo your wrong.
The point is that all Integer values under a certain bound (128 maybe?) are cached for efficiency when dealing with autoboxing. When creating aa and bb it simply returns the Integer object that was cached on VM startup so the references are identical and the native equality returns true. 1000 is above this bound, so a and b point to two different instantiations of the Integer class- i.e.: we need to use the equals method (as documented in the spec) to test for object equality, not ==.
>>8
Ridiculous as it may be industry has shown time and time again backwards compatibility is more important than usability or consistency. I'm sure the Java developers were just as upset with their implementation as you- but they have to shoehorn it in without breaking anything and complaining about this is kind of beating a dead horse.
>>15
Backward compatibility only explains why it isn't fixed now. It doesn't explain why it was done that way in the first place. It was just as bad an idea in Java 1.5, when it was introduced, as it is now, in Java 1.6.
>>16
Backwards compatibility does explain why it was broken in the first place.
Java was designed as an Object Oriented language, but because of efficiency and adoption concerns (Purely OO languages were quite radical at the time) they took the safe route and decided to retain primitive types. They have been paying for this ever since.
The introduction of generic typing meant that companion classes needed to be created for each primitive type (Allowing primitives to be used for creating generic types is not feasible when considering type erasure among other things).
Thus, we finally arrive at autoboxing as a solution to the inconvenience caused by having to interchange between OO and primitive types.
How else would you have done it- all things considered?
Name:
Anonymous2010-05-17 21:44
>>17
I'd have let auto-unboxing apply to the full range of Integers, and not just the limited -127 to 128. I don't buy that this is a caching issue, and even if it is, sacrificing correctness on this scale for a tiny bit of speed gain is retarded.
>>18
Are you retarded? Auto-unboxing _does_ apply to every integer- the problem is as described in >>14. Now that we agree it is a caching issue; let me point out it's NOT sacrificing correctness. The spec states that "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."
You would also be surprised how often some integers are boxed, and having to create a new Integer object for every one of them can over time create a significant enough performance hit to warrant this optimization. Either way, complaining over an optimizing compiler that conforms to the spec is kind of stupid.
>>19
Reading comprehension isn't your strong suit, is it?
Name:
Anonymous2010-05-17 21:56
>>18
Reread the thread again.
There is no auto-unboxing.
System.out.println(new Integer(0) == new Integer(0))
>false
== checks that references are the same.
>I don't buy that this is a caching issue,
And Earth is flat.You can believe whatever you want, check Integer.valueOf
public static Integer valueOf(int i) {
final int offset = 128;
if (i >= -128 && i <= 127) { // must cache
return IntegerCache.cache[i + offset];
}
return new Integer(i);
}
Now check source code of [javap -c]
class a{
public static void main(String [] args){
Integer aa = 1;
System.out.println(aa == 1);
}}
Guess what? It uses valueOf. Which uses cache:
public static void main(java.lang.String[]);
Signature: ([Ljava/lang/String;)V
Code:
Stack=3, Locals=2, Args_size=1
0: iconst_1
1: invokestatic #2; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
it's calling Integer.valueOf. Which uses cache.
>sacrificing correctness on this scale for a tiny bit of speed gain is retarded.
it is.
>>21 And Earth is flat.
I know what it does in terms of caching, dipshit, and I know the justification for it. I'm saying that the justification isn't sufficient.
>>22
Do you want to clarify what you are saying? Auto-unboxing works for all integers a la public class Boxing {
public static void main(String[] args) {
int i = new Integer(Integer.MAX_VALUE);
System.out.println(i + "");
}
} I'd have let auto-unboxing apply to the full range of Integers, and not just the limited -127 to 128
I'm going to assume you aren't saying we should cache every integer?
>>24
We can either remove the caching or store a table of already seen Integer objects and reference into it. The second options is obviously impractical, while the first can be done easily. The question is, why do we need to make an operation with undefined behavior "consistent" on its results?
>>26 HIBT? If p is a value of type int, then boxing conversion converts p into a reference r of class and type Integer, such that r.intValue() == p
In general, using == on two integers produces undefined behavior. What is so hard to understand about this?
>>29
In the general case it doesn't specify what == evaluates to, given "equal" or "unequal" Integers. Nitpicking on the definition of undefined doesn't really help your argument. Given two Integers n1, n2; the result of n1 == n2 is implementation defined if both n1, n2 are greater than 127 or less than -128, as intValue gives no guaruntee about reference locations besides these.
>>30
That doesn't mean it's undefined, that means it just compares the references like it does for any other object. It still returns true or false (usually false). Jesus fucking Christ.
The problem is that it should be part of the language specification that it returns true if the integers are equal, or that it should compare by reference even if the value is in the -127 to 128 range. Consistency.
Since the former change can be made without breaking backward compatibility and the latter probably can't, it should be the former.
Name:
Anonymous2010-05-17 23:13
>>27
Answer: no.
All Java Objects, when attempted to be compared using simple binary logic, will always produce false.
One exception to this rule, as demonstrated by this thread, is a silly technicality with Integer that allows caching of an int value between -128 and 127. However, this is the wrong way to initialize the Integer object and should be viewed as a curiosity.
>>30
Incorrect.
Trying to perform: Integer a = new Integer(0);
Integer b = new Integer(0);
System.out.println("Result of binary operation: " + (a == b));
will produce the output: Result of binary operation: false
>>31
The specification is perfectly consistent. The == operator will always compare reference values for objects. That is about as consistent as you can get; and in fact if it specified "[==] returns true if the integers are equal" this would be breaking backwards compatibility which was exactly my point to begin with.
The only way it wouldn't break would be if it specified two equal Integer objects must always have the same reference; and this is exactly what I was pointing out was impractical in >>25.
As for the -127 to 128 issue. This can't be resolved now either as it would break compatibility also, so it's stuck as is. If you are arguing it shouldn't have been done in the first place for consistency- I would have to disagree.
The very nature of the comparison is inconsistent. The spec makes no provisions for what reference locations should be allocated by the VM and in general (as mentioned above) there is no way to tell whether two Integers are ==. You are esentially saying we should make the behavior consistent in its inconsistency- what the hell?
>>33-34
Now you're just grasping at fucking straws. You've realised you're wrong, but you're too much of a twit to admit it.
Here's a hint concerning the advantages of anonymous posting: if you just leave the thread, nobody's going to know it was you.
In fact, give me one instance where a correctly-initialized Java non-primitive correctly compares against another correctly-initialized Java non-primitive using a == b and returns true if both non-primitives contain the same data.
>>37 String s1 = new String("cats");
String s2 = new String("cats");
BigInteger b1 = new BigInteger("0");
BigInteger b2 = new BigInteger("0");
On my virtual machine which conforms to the spec and optimizes strings and bigints to save space both s1 == s2 and b1 == b2. The fact that yours doesn't is irrelevant. Please leave the men to continue their discussion.
>>41
If you're going to accept that, you should also accept that the Integer behavior is defined and specified.
>>40
You're full of shit, of course, but if you did have a VM like that, it wouldn't conform to the spec. The discussion was over several posts ago, but you're too immature to admit it.
And note the careful rewording of:
"Strings computed at run time are newly created and therefore distinct. "
into:
"Strings computed by concatenation at run time are newly created and therefore distinct. "
>>44
At first that String comparison demonstration made me question my sanity but the very next second I realized what was going on.
What's the moral of this thread? In Java, the differences between Object variable = value; and Object variable = new Object(value); can not be taken for granted?