What is happening when a java.lang.Double object is initialized without using a call to the constructor but instead using a primitive? It appears to work but I'm not quite sure why. Is there some kind of implicit conversion going on with the compiler? This is using Java 5.
public class Foo {
public static void main(String[] args) {
Double d = 5.1;
System.out.println(d.toString());
}
}
This is called Autoboxing which is a feature that was added in Java 5. It will automatically convert between primitive types and the wrapper types such as double (the primitive) and java.lang.Double (the object wrapper). The java compiler automatically transforms the line:
Double d = 5.1;
into:
Double d = Double.valueOf(5.1);
It is called AutoBoxing
Autoboxing and Auto-Unboxing of
Primitive Types Converting between
primitive types, like int, boolean,
and their equivalent Object-based
counterparts like Integer and Boolean,
can require unnecessary amounts of
extra coding, especially if the
conversion is only needed for a method
call to the Collections API, for
example.
The autoboxing and auto-unboxing of
Java primitives produces code that is
more concise and easier to follow. In
the next example an int is being
stored and then retrieved from an
ArrayList. The 5.0 version leaves the
conversion required to transition to
an Integer and back to the compiler.
Before
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(0, new Integer(42));
int total = (list.get(0)).intValue();
After
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(0, 42);
int total = list.get(0);
It's called autoboxing.
Related
I'm learning about generics and am slightly confused.
I'm confused about the difference between the input type and returned type for a class using generics.
Stack<Integer> even = new Stack<>();
// pushing values in stack
even.push(0);
even.push(2);
System.out.println(even.pop().getClass().getSimpleName());
System.out.println("pop => " + even.pop());
We are pushing in an int value of 0 and 2.
But the first print statement will print "Integer".
If the stack is declared with Integer as its generic type, why are we able to push in a primitive "int"?
If we can push in a primitive "int" why is the pop() class returning a wrapper class "Integer"?
I'm clearly misunderstanding something about generics.
It happens because of someting called autoboxing.
Autoboxing is the automatic conversion that the Java compiler makes between the primitive types and their corresponding object wrapper classes. For example, converting an int to an Integer, a double to a Double, and so on. If the conversion goes the other way, this is called unboxing.
The simplest example:
Character ch = 'a';
That is what happens here:
List<Integer> li = new ArrayList<>();
for (int i = 1; i < 50; i += 2)
li.add(i);
The compiler creates an Integer object from i and adds the object to the list.
List<Integer> li = new ArrayList<>();
for (int i = 1; i < 50; i += 2)
li.add(Integer.valueOf(i));
The same thing for you stack.
You cannot have a generics declared as primitive types, because they are not classes. They are other thing (primitive types, of course). Instead, you use the corresponding wrapper class.
When you do the push(int), there is an implicit cast to the wrapper class Integer via the Integer#valueOf(int) method.
stack.push(0);
Is transformed, by the compiler and without asking into this
stack.push(Integer.valueOf(0))
For the same reason, you can do something like this
Integer n = 3;
And get no errors.
I have an ArrayList with type Long,but i am trying to insert int value in it.I am expecting int should also be stored in ArrayList as int is smaller in size than long.
int i=1;
ArrayList<Long> obj=new ArrayList<Long>();
obj.add(i);//It is showing error that Storing int is not possible
Whereas the below one is possible
List item
long l=0;
int i=5;
l=i;
Please suggest the reason why ArrayList can't store lower value types.
This:
ArrayList<Long> obj=new ArrayList<Long>();
is declaring that the list will store objects of type Long. It's storing references, and you can't put an Integer in, since an Integer is-not a Long (from the point of view of an object hierachy)
Don't think of the issue in term of numbers. Instead, try this. You have a list of Cats. You can't store a Dog in there. But you could if the list was declared as a list of Animals.
You could declare the list to contain a Number (Longs and Integers are both Numbers), but the fundamental issue is why are you mixing integers and longs in this collection ?
You are doing this:
Long l = 0L;
int i = 5;
l=i;//Type mismatch: cannot convert from int to Long
not this:
long l = 0;
int i = 5;
l = i;
It is not an ArrayList matter, look at this for details.
You just need to cast it to a long to make the above code work:
obj.add((long)i);
Because you specified that the ArrayList contains "Long", it forces all objects that go into it to be Long. And since ArrayList can be used to store any type of data, not just numbers, it doesn't have built-in mechanisms to convert ints to longs for example. Different rules apply.
Java primitives, like int and long, allow automatic conversion to comply with the way that C and C++ work, since Java was based on these languages originally. But it doesn't lead to the cleanest/safest code, and so some other more modern languages have removed even this type of fuziness.
The long variable l also can't store lower value types. The assignment of i to l will implicitly do a Widening Primitive Conversion, and the value is stored as a long.
When you try to insert an int value into a List<Long>, you're implicitly trying to do two conversions:
Widening Primitive Conversion (int to long)
Boxing Conversion (long to Long)
That double conversion will not be applied implicitly, so you have to tell the compiler to do it, by forcing the widening primitive conversion using a cast:
obj.add((long)i);
You have declared obj to be a list of Long and thus it restricts you to use add
/**
* Appends the specified element to the end of this list.
*
* #param e element to be appended to this list
* #return <tt>true</tt> (as specified by {#link Collection#add})
*/
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
Note - where E is from the class definition ArrayList<E> extends AbstractList<E>
to primarily add only the type that your list should be consisting of. Hence changing the code as follows should work :
int i=1;
ArrayList<Long> obj=new ArrayList<Long>();
obj.add(Long.valueOf(i));
Also in your latter part the cast is taken care by the = operator as you assign it in following way :
l=i;
An ArrayList<Long> can only store instances of Long.
You can "apparently" store longs in it, because the long is autoboxed to a Long:
list.add(someLong)
gets compiled to
list.add(Long.valueOf(someLong))
Boxing conversion only applies from primitive to corresponding wrapper type: long to Long, int to Integer etc. It doesn't box an int to a Long, however. The compiler isn't that smart/lenient.
And Java doesn't widen an Integer to a Long, because widening isn't defined for those types: it's only defined for primitive numeric types.
You've just got to make the parameter a long, then it can autobox for you:
obj.add((long) i);
or, without autoboxing:
obj.add(Long.valueOf(i));
Note, in the latter case, int is an acceptable parameter for a method taking a long parameter because of widening conversion. Widening + autoboxing just isn't supported.
A Wrapper Class is used to convert primitive into object and object into primitive. Similarly by using Autoboxing and Unboxing we can do the same then what is the difference in these two:
1-Concept wise
2-Code wise???
Auto-boxing and auto-unboxing is just the compiler silently helping you create and use primitive wrapper objects.
For example, the int primitive type has wrapper class called Integer. You wrap and unwrap as follows:
int myInt = 7;
// Wrap the primitive value
Integer myWrappedInt = Integer.valueOf(myInt);
// Unwrap the value
int myOtherInt = myWrappedInt.intValue();
With auto-boxing and auto-unboxing, you don't have to do all that boiler-plate stuff:
int myInt = 7;
// Wrap the primitive value
Integer myWrappedInt = myInt; // Compiler auto-boxes
// Unwrap the value
int myOtherInt = myWrappedInt; // Compiler auto-unboxes
It's just a syntactic sugar, handled by the compiler. The generated byte code is the same.
Wrapper classes in java provides a mechanism to convert primitive into object and object into primitive. Whereas automatic boxing and unboxing allows you to do that conversion automatically. Autoboxing and auto unboxing are legal in java since Java 5.
public class Main {
public static void main(String[] args) {
int x=100;
Integer iob;
iob=x;//illegal upto JDK1.4
iob= Integer.valueOf(x); //legal=> Boxing,Wrapping
iob=x; //Legal since JDK1.5=> Auto Boxing
}
}
Here x is a primitive variable, iob is a reference variable. So only an address can be assigned into this iob reference. iob=Integer.valueOf(x) will convert primitive integer into integer object. This conversion can be implied as wrapping. iob=x will do the same thing. It also saves a lot of coding.
public class Main {
public static void main(String[] args) {
Integer iob= new Integer(100);
int x;
x=iob;//illegal upto JDK1.4
x=iob.intValue(); //unboxing,unwrapping
x=iob; //legal since JDK1.5=> auto unboxing
}
}
Here iob.intValue() will take the value of integer object and it will assign that value into x. x=iob does the same thing except you don't need to write conversion code.
In java, It is said that "every thing instantiated other than primitive type is an object."
I am trying to understand this point using below code (line 4 to be specific).
public class dummy{
public static void main(String[] args){
int[] i = new int[2];
i[0] = new Integer(3); //line 4
i[1] = 3;
System.out.println(int[].class);
System.out.println(i[0]);
}
}
After running
int[] i = new int[4];
Java is creating an object [0,0] of type class [I. The two members within this object [0,0] are primitive data type(but not reference type).
My questions:
Why does Java allow assignment of an object to primitive type member as per below line?
i[0] = new Integer(3); // object of type 'class Integer' getting assigned to i[0]
How do I understand this? In counter, i[0] displays value 3 but not object address.
What is I in class [I? I mean, for class C{}; , C[].class gives class [LC
where [ means "array of" and LC means "instance of 'class C'"
i[0] = new Integer(3);
This involves what's known as auto-unboxing. In the Dark Ages of Java (pre-1.5) we used to have to explicitly box and unbox primitive types. But thankfully the language designers had pity on our poor fingers and added some syntactical sugar. They now let us convert freely between primitives and their wrapper types. Java secretly transforms the above code into this:
i[0] = new Integer(3).intValue();
That's auto-unboxing. Similarly, it will box values for you without your having to ask. If you write:
Integer i = 5;
Java will actually perform:
Integer i = Integer.valueOf(5);
What is I in class [I?
That's I for int.
Java is expecting you to assign an int to an element of the array, but you pass Integer, so it is automatically unboxed as int.
By the way, when you create an Integer[] array, you will also get the same result when doing System.out.println, because Integer.toString just creating the string of it's value, not "object address".
[ means one-dimensional array. I means int.
java/lang/Integer.intValue:()I is being called when you do i[0] = new Integer(3); //line 4 i.e, the compiler is implicitly getting the int value of the Integer and adding it in the array.
For your first question, Java autoboxes primitive types with their wrapper classes (for example, int gets wrapped into the Integer class) and also unboxes wrappers of primitive types.
Here is the documentation: http://docs.oracle.com/javase/tutorial/java/data/autoboxing.html
the compiler performs the conversion between primitives and their corresponding objects as a convenience for the programmer.
I have an Object obj that I know is actually a long.
In some Math code I need it as double.
Is it safe to directly cast it to double?
double x = (double)obj;
Or should I rather cast it first to long and then to double.
double x = (double)(long)obj;
I also found another (less readable) alternative:
double x = new Long((long)obj).doubleValue();
What are the dangers/implications of doing either?
Solution Summary:
obj is a Number and not a long.
Java 6 requires explicit casting, e.g.: double x = ((Number)obj).doubleValue()
Java 7 has working cast magic: double x = (long)obj
For more details on the Java6/7 issue also read discussion of TJ's answer.
Edit: I did some quick tests. Both ways of casting (explicit/magic) have the same performance.
As every primitive number in Java gets cast to its boxing type when an object is needed (in our case Long) and every boxed number is an instance of Number the safest way for doing so is:
final Object object = 0xdeadbeefL;
final double d = ((Number)object).doubleValue();
The danger here is, as always, that the Object we want to cast is not of type Number in which case you will get a ClassCastException. You may check the type of the object like
if(object instanceof Number) ...
if you like to prevent class cast exceptions and instead supply a default value like 0.0. Also silently failing methods are not always a good idea.
I have an Object obj that I know is actually a long.
No, you don't. long is a primitive data type, and primitive types in Java are not objects. Note that there's a difference between the primitive type long and java.lang.Long, which is a wrapper class.
You cannot cast a Long (object) to a long (primitive). To get the long value out of a Long, call longValue() on it:
Long obj = ...;
long value = obj.longValue();
Is it safe to directly cast it to double?
If it's actually a primitive long, then yes, you can cast that to a double. If it's a Long object, you don't need to cast, you can just call doubleValue() on it:
double x = obj.doubleValue();
Simple casting should work perfectly fine. This will be faster than going via the wrapper classes, getting string representation and then parsing to double, create new instance again using the long value - and more importantly, it's more readable.
double d = (double)15234451L;
You can cast it to a Long (since the Object is not a long but a Long), and then cast the Long to a double:
double d = (double)(Long)obj;
For instance, this has the expected output of 2.6666666666666665:
public class CastDouble {
public static final void main(String[] args) {
Object o = 15L;
System.out.println(40 / (double)(Long)o);
}
}
You only need one cast, from Object to Long or long (which implicitly casts to Long then applies unboxing):
Object o = 5L;
double d = (long) o; //Apparently only works on Java 7+
//or
double d = (Long) o;