Reputation: 77
I have this question,
vectors in java only accept objects right? but this piece of code compiles just fine
Vector myv=new Vector();
myv.addElement(1);
myv.addElement(1);
does it encapsulate it as an object of Integer? and if it does, why do this statement
System.out.println(myv.elementAt(0)==myv.elementAt(1));
gives true ?!!! they're supposed to be two distinct objects...?
at the same time this statement throws an error, which ensures that the element is an object.
int x=myv.elementAt(0);
can someone explain this for me? thank you.
Upvotes: 1
Views: 763
Reputation: 517
Java's Vector
is a generics, it means it can accept any kind of data to store. You have to specify the type of data to hold with a syntax like Vector<String>
. Replace String
for the kind of object you want the Vector
to hold.
The reason that it gives true
is because it is autoboxed into the Integer
class automatically; when compares two Integer
s, it does the same way as the built-in type int
.
EDIT: The autoboxing comparation works with the int
values in the range [-128;+127]
.
Upvotes: 0
Reputation: 3151
This is a feature of compiled code and auto-boxing.
Generics in Java are a compile-time issue. javac uses them to check that you use the types correctly, but the compiled byte code that's produced doesn't know anything about the generic types. Generics are implemented with type erasure in Java was mainly for backward compatibility. (That's also why raw types still exist in Java.)
It means that an Vector<E>
will look like a plain, raw Vector
at runtime - it's just a plain Vector
that contains objects. Since primitives are not objects, you can't store primitive types in such an Vector
.
There are wrapper classes for each of the primitive types (int -> Integer, long -> Long, short -> Short, boolean
--> Boolean, etc.) so is possible to make it such that a Vector<int>
would use auto-boxing to store ints in Integer
objects, which could be stored in a Vector
. ...but the designers of the Java language didn't decide to take auto-boxing that far.
Upvotes: 0
Reputation: 3035
This is called autoboxing. When the Java compiler encounters an integer, float or double value in a place where an object is expected, it automatically creates a wrapper object.
The code generated by the compiler for your code is equivalent to
Vector myv=new Vector();
myv.addElement(Integer.valueOf(1));
myv.addElement(Integer.valueOf(1));
The valueOf() method caches Integer instances for the values from -128 to 127 (IIRC), with the result that both values will be replaced by the same object.
Try the same with a lager value, like 1000. Then the objects will be different.
Upvotes: 1
Reputation: 1863
Here is something pretty funny about Java, it caches integers between -128 and 127 (for auto-/un-boxing) and any reference to integers in that range all refer to the same object (since == here is comparing Objects). This can cause quite a few bugs when people don't thing through the ==
method comparing Objects, rather than values.
So you will get true
for comparing "integers" (autoboxed) between -128 - 127. If you do the same thing with 128
, it'll say false.
Check it out:
import java.util.Vector;
public class Vect {
public static void main(String[] args) {
Vector v = new Vector();
v.addElement(127);
v.addElement(127);
v.addElement(128);
v.addElement(128);
System.out.println(v.elementAt(0) == v.elementAt(1));
System.out.println(v.elementAt(2) == v.elementAt(3));
}
}
Will give you:
$ java Vect
true
false
Upvotes: 1
Reputation: 22233
That works because java auto boxes and auto unboxes these type for you.
But note that this doesn't work for sure in every scenario.
Let's take this example:
Integer i = 1234;
Integer z = 1234;
System.out.println("i: "+i);
System.out.println("z: "+z);
System.out.println("== : "+(i == z));
System.out.println("equals: "+i.equals(z));
It will produce the following output:
i: 1234
z: 1234
== : false
equals: true
In fact, from this answer you can see that it works only for integers between -128 and +127
In fact, this behaves as expected:
Integer i = 123;
Integer z = 123;
System.out.println("i: "+i);
System.out.println("z: "+z);
System.out.println("== : "+(i == z));
System.out.println("equals: "+i.equals(z));
and produces:
i: 123
z: 123
== : true
equals: true
Upvotes: 1
Reputation: 5486
The 1
is auto-boxed into an Integer.
To learn more about Autoboxing and -unboxing, see Oracle's Docu: https://docs.oracle.com/javase/tutorial/java/data/autoboxing.html
On why they are the same: Autoboxing ints to Integers uses a cache. For numbers < 128 (I think) the same Integer-Object will be returned each time instead of a new one being created. So your code essentially inserts the same object twice into the Vector, and for this reason the identity comparison using ==
returns true.
As you don't use generics with your Vector, myv.elementAt(0)
will return an Object, which cannot be cast to an int. If you used generics, i.e. Vector<Integer> myv = new Vector<>()
, then elementAt
would return an Integer which would be auto-unboxed to an int
.
Upvotes: 9