I was doing one of these online Java tests and I was asked this question:
Q: Indicate correct assignment:
Long l = 1;
Double d = 1;
Integer i = 1;
String s = 1;
Object o = "1";
System.out.println(o);
o = 1;
System.out.println(o);
Please try it yourself before you go any further.
Well I can tell you I got it wrong, I investigated it and found:
//Long l = 1; //cannot widen and then box
Long ll = 1L;//no need to widen, just box
//Double d = 1;//cannot widen and then box
Double dd = 1d;//no need to widen, just box
Integer i = 1;//no need to widen, just box
//String s = 1;//cannot do implicit casting here
Object o = "1";//this compiles and is just plain weird
System.out.println(o);//output is 1
o = 1;//this also compiles and is also weird
System.out.println(o);//output is 1
Can someone tell why:
Object o = 1; and Object o = "1";
compile and output 1 in both cases, this is puzzling me.
Many thanks
"1" is an instance of String class, and String is a subclass of Object class in Java (as any other class). 1 is boxed into an Integer, which is also derived from Object.
Because "1" is an instance of a String, and since 1.5 1 is auto-boxable to an Integer; both types are subtypes of Object. Before autoboxing was introduced, Object o = 1; would not compile.
To get the most out of this learning experience, you should be aware of Object's getClass() method. By adding System.out.println(o.getClass().getName()), you can also print the name of the class that the object referred to by o belongs to. In your case, they are java.lang.String (for (Object) "1") and java.lang.Integer (for (Object) 1).
Just for completion, I should mention that you can now also do Object o = false;.
Well, the first case "1" is a String literal, so a subclass of object, hence assignable to it. As a string, it output of 1 is relatively simple.
In the second case, auto-boxing is occurring. Integer is a subclass of object, hence assignable to it. Similarly, the output of 1 then makes perfect sense.
This is because o is of type Object. Every object, in java, extends the class Object. So... when you say Object o = 1, it converts 1 to from int to Integer, which is an Object. Similarly, "1" is a String which is an Object. In both cases, calling System.out.println on an Object invokes the Objects toString method. In both cases, it will print 1.
You can put Object o = anything; where anything is any object because all classes derive from the Object class. It works with primitives because of autoboxing feature which came in java 1.5.
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 was reading earlier that wrapper classes are all immutable. Immutable means that the value cannot be changed. Below I tried this simple example that can just be pasted in to any main method. first I create a Integer that wraps the value five. Immutable means that they cannot be changed so why can I set I to 89. I think that it is because it changes where (I) points to but I am not certain why this is the case.
In my next little example i create an Integer of x which will throw an error if I try and change it. The x seems to be immutable in this specific case but not in the case of the (i) variable.
It seems that I can change the value of (i) whenever I want to so in reality Integer without the final keyword is not immutable???? If i can be set to 89 then to me this seems that the variable can be changed.
I have read other post on this and I still am not certain why i can be changed to another variable. Also in writing code what is the best way to declare primitive types. Why not use the wrapper classes all of the time to create variables.
int y = 5;
Integer i = new Integer(y);
i = 89;
final Integer x = Integer.valueOf(5);
System.out.println("Integer:(i) " + i.intValue());
System.out.println("Integer:(i) " + i.byteValue());
System.out.println("Integer:(x) " + x.intValue());;
System.out.println("Integer:(x) " + x.byteValue());;
i = i - 5;
Using all wrapper classes to declare variables: (Would this be better than declaring these variable with the primitive variable types)
Integer a = new integer(MyNewValue);
Integer b = new integer(MyNewValue);
Integer c = new integer(MyNewValue);
Integer d = new integer(MyNewValue);
Float fa = new integer(MyNewValue);
You are conflating two things: changing the value of an "object" itself and changing the object a reference points to. Saying i = 89 just points the variable i to a new object; it doesn't change the Integer object which originally was pointed to by i.
Pre-pending variable declarations with final just ensures that reassigned is prohibited, it is in no way a declaration of the mutability/immutability of the object it points to. Maybe off-topic, but I personally think the article Java is Pass-by-Value, Dammit! is a good read.
When you call i = 89;, your not changing the value of the Integer object stored in memory. Instead, you're assigning a brand new int with value 89 to i. So the immutable rule isn't being broken.
Remember that i is simply a reference that points to the Integer, not the actual Integer itself.
Yes, it does look like the integer is changing, but all that is happening on line 3 is its being converted to i = new Integer(89) by the compiler. If you wanted to see, you could do
Integer i1 = i;
i = 83;
println(i); \\ prints out the original value 5
println(i1); \\ prints out a new value, 83
When you declare something as final, you cannot change the definition of the variable, though you can still mutate anything inside it. JavaRanch has a very nice analogy to help
You should not use wrapper objects when you can avoid it because they are a small amount less efficient to than primitives and take up a few extra bytes.
I'm curious about java initialization:
When is it necessary to initialize objects like this:
String init = new String("");
and which objects - like Strings - don't have to be initialized like above?
String init = "";
From your comment on your question:
Then my question is which objects need the "new Object()" initialization?
You're asking about construction, not initialization.
All objects need to be constructed by someone. The strings created by string literals are constructed by the JVM. You basically never want to use new String("text content here").
There are several other objects constructed by the JVM, such as the Class object for each class you load. But other than String, for objects you want to interact with, you usually either have to explicitly construct them (via new) or receive them from a method that constructs them. String is a bit special because it's the only object type in Java (I think) with a literal notation. (All of the other literals, like 42 or false, are primitives.)
Basically there's a subtle difference between the 2 ways of initialization you mentioned:
When you use:
String str = new String("");
a new String object is created on the heap and str points to it.
But in the latter case:
String str = "";
If there is already a string with this value ("") on the string pool, then the reference is initialized to point to it and no new object is created. If it is not found in the string pool, then a new string is created in the string pool and str is initialized to point to it.
For strings, you almost always want to use the second form. It does less work for what -- in most circumstances -- is the same result.
The same advice goes for numeric classes, such as Integer, Double, etc.
In all other cases you don't normally have the choice, and have to use the first form.
In Java, all objects must be initialized. The second case init = "" is also an initialization, except that the compiler lets you avoid the explicit call: object creation is still there. Starting with Java 5, the compiler also "knows" about wrappers for Java primitives, letting you use primitive constants in expressions that require a wrapper class (this is called autoboxing).
All local variables must be initialized explicitly, while member fields can be initialized implicitly to null or the default value of the primitive.
Most classes require explicit construction (the new), however a few classes does not, these are the autoboxing classes (String, Integer, Double, and a few more, as well as arrays of these (using the comma seperated list initiliazation)) and these are the only ones!
What happens at the compiler level is really just that the compiler translates the implicit construction to an explicit one (e.g. One using new)
All objects need to be initialized before they can be used. You can try declaring:
int myPrimitiveInt;
Integer myObjectInt;
But myPrimitiveInt cannot be used until you give it a value, and myObjectInt is implicitly initialized as null. For either of these to be used (except to get a null from the object), they need to be given a value, whether you use a constructor or not.
myPrimitiveInt = 5;
myObjectInt = new Integer(5);
myObjectInt = 5;
String s1 = "1";
String s2 = new String("2");
int i1 = 1;
int i2 = new Integer(2);
long l1 = 1l;
long l2 = new Long(2l);
float f1 = 1f;
float f2 = new Float(2f);
double d1 = 1d;
double d2 = new Double(2d);
char c1 = '1';
char c2 = new Character('2');
byte b1 = 1;
byte b2 = new Byte((byte) 2);
int[] a1 = {1};
int[] a2 = new int[] {2};
All Objects have to be initialized with new but some, like these for example:
String myString= "";
Integer myInteger= 2;
Float myFloat= 2f;
Double myDouble= 2d;
Byte myByte = 2;
and every kind of array, which can be initialized like `T[] array = {//list some Ts};
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;
What is the difference between them?
l is an arraylist of Integer type.
version 1:
int[] a = new int[l.size()];
for (int i = 0; i < l.size(); i++) {
a[i] = l.get(i);
}
return a;
version 2:
int[] a = new int[l.size()];
for (int i = 0; i < l.size(); i++) {
a[i] = l.get(i).intValue();
}
return a;
l.get(i); will return Integer and then calling intValue(); on it will return the integer as type int.
Converting an int to Integer is called boxing.
Converting an Integer to int is called unboxing
And so on for conversion between other primitive types and their corresponding Wrapper classes.
Since java 5, it will automatically do the required conversions for you(autoboxing), so there is no difference in your examples if you are working with Java 5 or later. The only thing you have to look after is if an Integer is null, and you directly assign it to int then it will throw NullPointerException.
Prior to java 5, the programmer himself had to do boxing/unboxing.
As you noticed, intValue is not of much use when you already know you have an Integer. However, this method is not declared in Integer, but in the general Number class. In a situation where all you know is that you have some Number, you'll realize the utility of that method.
The Object returned by l.get(i) is an instance of the Integer class.
intValue() is a instance method of the Integer class that returns a primitive int.
See Java reference doc...
http://docs.oracle.com/javase/6/docs/api/java/lang/Integer.html#intValue()
Java support two types of structures first are primitives, second are Objects.
Method that you are asking, is used to retrieve value from Object to primitive.
All java types that represent number extend class Number. This methods are in someway deprecated if you use same primitive and object type since [autoboxing] was implemented in Java 1.5.
int - primitive
Integer - object
Before Java 1.5 we was force to write
int i = integer.intValue();
since Java 1.5 we can write
int i = integer;
Those methods are also used when we need to change our type from Integer to long
long l = integer.longValue();
Consider this example:
Integer i = new Integer(10);
Integer j = new Integer(10);
if (!(i == j)) {
System.out.println("Surprise, doesn't match!");
}
if (i.intValue() == j.intValue()) {
System.out.println("Cool, matches now!");
}
which prints
Surprise, doesn't match!
Cool, matches now!
That proves that intValue() is of great relevance. More so because Java does not allow to store primitive types directly into the containers, and very often we need to compare the values stored in them. For example:
oneStack.peek() == anotherStack.peek()
doesn't work the way we usually expects it to work, while the below statement does the job, much like a workaround:
oneStack.peek().intValue() == anotherStack.peek().intValue()
get(i) will return Integer object and will get its value when you call intValue().In first case, automatically auto-unboxing happens.
They are exactly the same. As other posters have mentioned, you can put either the Integer object or the int primitive into the array. In the first case, the compiler will automatically convert the Integer object into a primitive. This is called auto-boxing.
It's just a convenience method for getting primitive value from object of Number: http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/Number.html
Consider the code:
Integer integerValue = Integer.valueOf(123);
float floatValue = integerValue.floatValue();
The last line is a convenient method to do:
float floatValue = (float)(int)integerValue;
Since any numeric type in Java can be explicitly cast to any other primitive numeric type, Number class implements all these conversions. As usual, some of them don't make much sense:
Integer integerValue = Integer.valueOf(123);
int intValue = integerValue.intValue();
int intValue2 = (int)integerValue;
int intValue3 = integerValue;