msLangdon95
msLangdon95

Reputation: 77

vectors in java contains only objects?

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

Answers (6)

SonicARG
SonicARG

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

Upvotes: 0

Keith
Keith

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

Thomas Stets
Thomas Stets

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

nerdwaller
nerdwaller

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

BackSlash
BackSlash

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

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

Upvotes: 1

cello
cello

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

Related Questions