vectors in java contains only objects? - java

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.

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.

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

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

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.

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.

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

Related

create a new Integer object that holds the value 1?

To create a new Integer object that holds the value in java 1 which one of the following is right and what exactly is the difference in the following methods as all print the value?
Method 1 :
Integer p = new Integer(1);
Method 2 :
Integer p = 1;
Method 3 :
Integer p = new Integer("1");
Using method three I got the following warning :
Note: HelloWorld.java uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details
You skipped the intended solution:
Integer p = Integer.valueOf(1);
This pattern is known as Factory method pattern. One may ask what the benefit of this method is. Luckily, the implementation of class Integer is open-source, so let's take a look:
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
There seems to be some kind of Integer-value cache. If one requests an Integer with a value within the cache-range, Java does not create a new object, but returns a previously created one. This works because Integers are immutable. One can even control the upper cache limit with the system property java.lang.Integer.IntegerCache.high=....
And why do the other two methods of creating an Integer generate a warning? Because they were set deprecated with Java 9.
Integer#Integer(int value):
Deprecated. It is rarely appropriate to use this constructor. The static factory valueOf(int) is generally a better choice, as it is likely to yield significantly better space and time performance. [...]
Integer#Integer(String s):
Deprecated. It is rarely appropriate to use this constructor. Use parseInt(String) to convert a string to a int primitive, or use valueOf(String) to convert a string to an Integer object. [...]
And just for completeness, here is the part for Integer.valueOf(int i):
Returns an Integer instance representing the specified int value. If a new Integer instance is not required, this method should generally be used in preference to the constructor Integer(int), as this method is likely to yield significantly better space and time performance by caching frequently requested values. This method will always cache values in the range -128 to 127, inclusive, and may cache other values outside of this range.
EDIT 1: Thanks to #VGR mentioning that
Integer p = 1;
is equivilant to
Integer p = Integer.valueOf(1);
This, however, is only true for int-values between -128 and 127. The behaviour is defined in JLS §5.1.7:
[...] If the value p being boxed is the result of evaluating a constant expression (§15.28) of type boolean, char, short, int, or long, and the result is true, false, a character in the range '\u0000' to '\u007f' inclusive, or an integer in the range -128 to 127 inclusive, then let a and b be the results of any two boxing conversions of p. It is always the case that a == b.
EDIT 2: Thanks to #DorianGray, who brought the following to my attention.
While not in the JLS, the version of javac I am using (9.0.4) does compile the boxing down to Integer.valueOf(...); as it is shown in this answer by Adam Rosenfield.
Method 4, Integer p = Integer.valueOf(1); is the recommended way. The JavaDoc says:
Returns an Integer instance representing the specified int value. If a
new Integer instance is not required, this method should generally be
used in preference to the constructor Integer(int), as this method is
likely to yield significantly better space and time performance by
caching frequently requested values. This method will always cache
values in the range -128 to 127, inclusive, and may cache other values
outside of this range.

Why same values got from ArrayList are changed to different ones?

I am using Java ArrayList.
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(-129);
list.add(-129);
return (list.get(0) == list.get(1));
The return value is false.
I know it must be some range problem since when I use -128, it returns true.
But could someone tell me the reason of it?
Java caches integers in the range -128..127 (signed bytes). It saves a lot of allocations of tiny numbers which is very common in lots of code. If you use equals() instead of ==, it will work. The == check is comparing that two int types, that have been magically boxed (i.e. converted) to Integer are the same reference - which they are not. But int in the signed byte range will be the same. The equals check will actually compare the value of the variables:
return (list.get(0).equals(list.get(1)));
When you perform:
list.add(-129);
list.add(-129);
It create two separate object with separate memory location.when you perform == it return false.
In Java, values from -128 to 127 are cached, so the same objects are returned and you will get true.
For more information see:http://www.geeksforgeeks.org/comparison-autoboxed-integer-objects-java/
If two references point to two different objects, then in accordance with the "= =" to judge both is unequal, even though both have the same reference content. As we know, if two references refer to the same object, in accordance with the "= =" to judge the two are equal.
If you go to the Integer. Java classes, you will find that there is a internal private class IntegerCache. Java, it caches from all the Integer object - between 128 ~ 127.
So the thing is, all the small integers are in the internal cache.
If the value is between 128 ~ 127, then it will be returned from a cache instance,point to the same object.

Why does comparing Integers by reference (==) work?

In Herbert Schildt's "Java: The Complete Reference, 9th Edition", there's an example that kinda baffles me. Its key point that i can't comprehend could be summed up to the following code:
class Test {
public static void main (String args[]) {
Integer i1 = 6;
Integer i2 = 6;
Integer i3 = 6;
Integer i4 = (args.length + 1) * 6;
if (i1 == i2) System.out.println("WTF");
if (i3 == i4) System.out.println("Super WTF!!!");
}
}
To my surprise, the result of compiling and executing such code using JDK 8 update 40 is as follows:
WTF
Super WTF!!!
All the Java books, manuals and other informational resources that i've seen state that the equality operator (==), when used to compare objects, simply matches their reference values. So, if two object variables refer to distinct instances, then the == operator returns false, even if the internal contents of those objects are the same. Which is quite different from the behavior expressed by the example above.
While checking SO for similar questions, i found a somewhat related one, which is about comparing String objects using ==. There, an interesting feature of Java called interning was mentioned. Apparently, all the string literals and compile-time string constants are sort of "cached" by JVM, so that, for example, multiple String references initialized with the same string literals actually point to the same object.
But here we deal with numeric values and Integer objects. Also, one of the variables, i4, is initialized using a number of command line arguments supplied to the program, which is definitely a run-time information. Yet, == still finds it equal to i3.
So, given all the above, how exactly is the equality operator supposed to work in Java? Does it, or does it not, inspect the objects' contents when comparing them?
Thanks!
Integer objects are cached as mentioned by the Javadocs of Integer#valueOf(int):
This method will always cache values in the range -128 to 127, inclusive, and may cache other values outside of this range.
The statement Integer i4 = (args.length + 1) * 6; calls Integer#valueOf(int) which returns the cached instance. On the other hand, if you use Integer i4 = new Integer((args.length + 1) * 6);, the reference equality will return false.
I think the example shows us how java int pool is working. So in the i4 case if you provided no arguments on runtime the result is 6. Now the int pool kicks in and uses the i1 value which is part of the -128 to to 127 int pool. So on an object level they really equal and that's what == is all about.
When you autobox an int, you're internally calling Integer.valueOf(int), which according to the documentation may return cached values. So it makes perfect sense that you're seeing reference equality.
More generally, you should never assume two references are distinct unless you explicitly constructed them. And for the record, string interning is available at runtime as well, through the String.intern() method.

Why does char to int casting works and not char to Integer in Java

I was working on a problem when I encountered this.
(int)input.charAt(i) //works
(Integer)input.charAt(i) // Does not work
// input being a string
The first thought I have is primitives are treated differently and that is why this is not working. But then I find it difficult to understand why would they have a Integer Wrapper class in the first place.
Edit:
What are the advantages of having wrapper classes then? Is it just for not having a primitives presence and being more OO in design? I'm finding it difficult to understand how are tehy helpful. New doubt altogetehr.
You're right that primitives are treated differently. The following would work:
(Integer)(int)input.charAt(i);
The difference is that when the argument is an int, (Integer) boxes the integer. It's not actually a cast even though it looks like it. But if the argument is a char, then it would be a cast attempt; but primitives can't be cast to objects and therefore it doesn't work. What you can do is to first cast the char to int - this cast is okay since both are primitive types - and then the int can be boxed.
Of course, char -> Integer boxing could have been made working. "Why not?" is a good question. Probably there would have been little use for such feature, especially when the same function can be achieved by being a little bit more explicit. (Should char -> Long work too, then? And char -> Short? chars are 16-bit, so this would be most straightforward.)
Answer to edit: the advantage of wrapper classes is that wrapped primitives can be treated like objects: stored in a List<Integer>, for example. List<int> would not work, because int is not an object. So maybe even more relevant question would be, what are primitive non-objects doing in an OO language? The answer is in performance: primitives are faster and take less memory. The use case determines whether the convenience of objects or the performance of primitives is more important.
Because Integer is an Object. and char is not. you cant cast a non Object thing to some Object.
Infact you cannot cast some Object to any other class Object which is not in the hierarchy of that Object.
eg you cannot do this
Integer g = (Integer) s;
where s is object of String.
Now why chat to int works, because every character is represented as unicode in java, so you can think of it as at backend char is a smaller version of int. (int is 32 bits and char is 16 bits)

Beginner Java Question about Integer.parseInt() and casting

so when casting like in the statement below :-
int randomNumber=(int) (Math.random()*5)
it causes the random no. generated to get converted into an int..
Also there's this method I just came across Integer.parseInt() which does the same !
i.e return an integer
Why two different ways to make a value an int ?
Also I made a search and it says parseInt() takes string as an argument.. So does this mean that parseInt() is ONLY to convert String into integer ?
What about this casting then (int) ?? Can we use this to convert a string to an int too ?
sorry if it sounds like a dumb question..I am just confused and trying to understand
Help ?
Integer.parseInt does not do the same thing as a cast.
Let's take a look at your first example:
int randomNumber=(int) (Math.random()*5)
Math.random returns a double, and when you multiply a double by an int Java considers the result to be a double. Thus the expression Math.random()*5 has a type of double. What you're trying to do is assign that value to a variable of type int. By default Java will not allow you to assign a double value to a variable of type int without your explicitly telling the compiler that it's ok to do so. Basically you can think of casting a double to an int as telling the compiler, "I know this int variable can't hold the decimal part of this double value, but that's ok, just truncate it."
Now take a look at the conversion of a String to an int:
int value = Integer.parseInt("5");
The string "5" is not immediately convertible to an integer. Unlike doubles, which by definition can be converted to an integer by dropping the decimal part, Strings can't be easily or consistently converted to an int. "5", "042", and "1,000" all have integer representations, but something like "Hello, World!" does not. Because of this there is no first order language feature for converting a String to an int. Instead, you use a method to parse the String and return the value.
So to answer all your questions:
Why two different ways to make a value an int ?
You have to take into account what the type of the value you are converting is. If you're converting a primitive to an int you can use a cast, if you're converting an Object you'll need to use some sort of conversion method specific to that type.
Also I made a search and it says parseInt() takes string as an argument.. So does this mean that parseInt() is ONLY to convert String into integer ?
Correct. You cannot pass any other type to the parseInt method or you will get a compiler error.
What about this casting then (int) ?? Can we use this to convert a string to an int too ?
No, casting to int will only work for primitive values, and in Java a String is not a primitive.
In your example, you are casting a floating-point number to an int. Integer.parseInt(), however, reads an integer value from a String.
You can only cast between compatible types (I'd link to the JLS but that might be too much for a beginner question).
Casting is basically just taking a value and saying, "Hey, this thing that was a double? Now it's an int. So there."
You can't do that with a string because it isn't anything like an int. You have to instead parse an int out of it, which is actually a lot harder than it sounds. Fortunately, it's already implemented for you so you don't have to worry about how it works.
Casting can only convert from one numeric type to another. Interpreting a string (aka parsing) needs to be done with a method call.
Let's start from the top.
int randomNumber=(int) (Math.random()*5);
Yes, this does indeed give a random integer between 0 and 4, but this is very much not the proper way of doing this. You see, if you forget a parenthesis, i.e. you type
int notSoRandomNumber=(int) Math.random()*5;
you'll always get 0 because casting has higher precedence than multiplication. That is to say the result of Math.random() is first coerced into an integer, which will always be 0 and then it's multiplied by 5, which is still 0.
I'd favour using java.util.Random for generating random integers. q.v. http://java.sun.com/javase/6/docs/api/java/util/Random.html#nextInt(int).
Casting can only be done between "compatible types". For primitive types and their wrappers (i.e. int, Integer, long, Long, &c.) you can always cast between them with the caveat that some conversions lose information. e.g. when casting a long to an int, the long may contain a number larger than Integer.MAX_VALUE]. This kind of casting Java basically got from C++ which it in turn got from C.
As for casting objects, it's actually simpler. Simply ask "is this object, o, an X?" If so then (X) o makes sense and has static type X. If o is not an X and you try to cast anyway, you'll get a ClassCastException signifying that o's dynamic (runtime) type is not compatible with X. This will probably make a lot more sense later when you get the difference between the static and the dynamic (runtime) type of objects.
Following code convert String to int without any methods
public class MyStringToNumber {
public static int convert_String_To_Number(String numStr){
char ch[] = numStr.toCharArray();
int sum = 0;
//get ascii value for zero
int zeroAscii = (int)'0'; // '0'=48 zeroAscii=48
for(int i=0;i<ch.length;i++){
int tmpAscii = (int)ch[i]; // for 0 ch[i]=3,3=51, tempAscii=51
// (0*10)+(51-48)
// 0 +3
// 3
// sum=3
// for 1 ch[i]=2,2=50, tempAscii=50
sum = (sum*10)+(tmpAscii-zeroAscii); // 0 +(51-48)=3 sum=3
// (3*10)=30+(50-48)
// 30 + 2
// sum=32
// for 2 ch[i]=5, 5=53 tempAscii=53
// (32*10)+(53-48)
// 320 + 5
// 325
// sum=325
// for 3 ch[i]=6,6=54, tempAscii=54
// (325*10)+(54-48)
// 3250 +6
// 3256
// sum=3256
}
return sum;
}
public static void main(String a[]){
System.out.println("\"3256\" == "+convert_String_To_Number("3256"));
}
}
Output "3256" --> 3256
Parse() method is available is many formats, Integer class having the method ParseInt() which is a static method, we to call this method by Integer.ParseInt()
Similarly Double class having ParseDouble()and we call it as Double.ParseDouble().
The more Generic way is XXXX.ParseXXXX()
The main use of this Method is to convert any Object into a Primitive.
And here you can raise a question why we need to convert into Primitives?
The answer is, we know that primitives are stored in stack area and objects are stored in Heap area, and you doesn't want to waste the Heap Memory and you can convert an Object into a Primitive.
And the other thing, while accessing any Object there may be Overhead.
It is better to use as a Primitive.

Categories