1

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.

msLangdon95
  • 77
  • 1
  • 13
  • 2
    You shouldn't be using `Vectors` anymore, use `ArrayList`. If you need thread safety, there are various options to accomplish that with the built ins. [Here](http://stackoverflow.com/questions/1792134/a-colleague-said-dont-use-java-util-vector-anymore-why-not#answer-1795468) are some good explanations. – nerdwaller Nov 12 '14 at 20:48
  • 1
    I know, I just want to understand this specific thing. thanks anyways. – msLangdon95 Nov 12 '14 at 20:50
  • Vectors are obsoleted – energizer Nov 12 '14 at 20:53
  • Same basic question as this, though maybe not a duplicate since the context is different http://stackoverflow.com/questions/22648627/how-java-auto-boxing-unboxing-works – en_Knight Nov 12 '14 at 20:54
  • Also "only accept objects" - sort of... You can use generics, so that a Vector won't even accept an "Object" object, but that isn't really your question. – en_Knight Nov 12 '14 at 20:56

6 Answers6

9

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.

cello
  • 5,356
  • 3
  • 23
  • 28
  • 1
    its -128 t 127 and it can be used for [mean things](http://codegolf.stackexchange.com/a/28818) – Dawnkeeper Nov 12 '14 at 20:57
  • @Programmer: please accept the answer as the right one if you think it is the right one for your question. – cello Nov 12 '14 at 21:57
1

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.

Thomas Stets
  • 3,015
  • 4
  • 17
  • 29
  • if the compiler would really generate two new Integer objects, the OPs second code example would not work. Actually, auto-boxing is a bit more complex and uses caches, so it would even put the same object twice to the list, and not two different/new objects. – cello Nov 12 '14 at 20:55
  • 1
    You are right, I missed the part about the equals. However, the Integer caching logic is not in the autoboxing, but rather in the Integer.valorOf(int). I'll fix my example. – Thomas Stets Nov 12 '14 at 20:59
1

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

DEMO

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

DEMO

Community
  • 1
  • 1
BackSlash
  • 21,927
  • 22
  • 96
  • 136
1

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
nerdwaller
  • 1,813
  • 1
  • 18
  • 19
0

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 Integers, 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].

SonicARG
  • 499
  • 9
  • 14
  • 1
    "when compares two Integers, it does the same way as the built-in type int." That isn't accurate - it's only values between -128 and 127 as those are cached and are actually the same object (as compared with `==`). – nerdwaller Nov 12 '14 at 20:59
  • Thanks for the data @nerdwaller, updating now the answer ;) – SonicARG Nov 12 '14 at 21:07
0

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.

Keith
  • 3,079
  • 2
  • 17
  • 26