Number in java how it work without a subclass? - java

I want to know why the result of this code:
Number x = 3;
System.out.println(x.intValue());
System.out.println(x.doubleValue());
generates
3
3.0
as Number is an abstract class in Java.
So when I need to use it - I could use it with some it's subclasses like Integer, Double ...etc. Now I want to know how exactly this part of code works:
Number x = 3;

when you do:
Number x = 3;
System.out.println(x.intValue());
System.out.println(x.doubleValue());
Following will happen:
Number x = 3;
this will declare x as int, and will be auto boxed to an object of the class Integer turning this: Number x = 3; into Number x = new Integer(3);
then here:
System.out.println(x.intValue());
intValue is implemented as:
public int intValue() {
return value;
}
System.out.println(x.doubleValue());
and doubleValue is implemented as:
public double doubleValue() {
return (double)value;
}

Auto Boxing.
So when you do
Number x = 3;
That gets compiled to
Number x = new Integer(3);
Number in java how it work without a subclass?
That is a wrong assumption. Number class have subclasses. If you look at the definition of Integer class.
Look at the definition of Integer class
public final class Integer
extends Number
It is a sublcass of Number so it gets compiled fine.

The key thing to understand here: the fact that you use Number on the left hand side of that assignment doesn't mean that the object referenced by x is in fact a direct instance of the Number class.
As others have outlined, auto-boxing kicks in here. One way to get to the true nature of things: by looking at the byte code:
0: iconst_3
1: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
4: astore_1
...
1: is about calling Integer.valueOf(int) - the method that turns the int value 3 into an Integer object!
The other easy way to get to the point - by doing:
System.out.println(x.getClass());
and that of course prints Integer; not Number!

Autoboxing helping to compile the code.
Converting a primitive value (an int, for example) into an object of the corresponding wrapper class (Integer) is called autoboxing
So compiler convert this code Number x = 3; to the following at runtime :
Number x = Integer.valueOf(3);

Following is an example of boxing and unboxing:
public class Test {
public static void main(String args[]) {
Integer x = 5; // boxes int to an Integer object
x = x + 10; // unboxes the Integer to a int
System.out.println(x);
}
}
This will produce the following result:
15
When x is assigned an integer value, the compiler boxes the integer because x is integer object. Later, x is unboxed so that they can be added as an integer.

Java has a feature called AutoBoxing, what it does is automatically wrapping primitives with it's corresponding object wrapper class.
Number x=3;
System.out.println(x.getClass());
Just try this and you will see what actually has happened.
Also try
Number x=3.0;
System.out.println(x.getClass());
In first case java wraps 3 with an Integer.class and in the second time it wraps 3.0 with a Double.class.
In your case, since it is getting wrapped as an Integer, when you call doubleValue() method, it actually calls doubleValue() in Integer.class which has the following implementation.
public double doubleValue() {
return (double)value;
}

Please find the below hierarchy of Number DataType
Direct Known Subclasses:
AtomicInteger, AtomicLong, BigDecimal, BigInteger, Byte, Double, Float, Integer, Long, Short

Related

Do wrapper class objects get unboxed while being assigned to another object?

When we assign objects of the same type to one another, the new object stores the address of the object that's being assigned to it. For instance, if I have my own class named CLA then the following code will produce 11 as the output:
public class CLA{
int val;
public static void main(String...args){
CLA ob1 = new CLA();
ob1.val = 10;
CLA ob2 = ob1;
ob1.val++;
System.out.printf("%d", ob2.val);
}
}
because ob2 would refer to ob1 and consequently show ob1's val.
However, the same doesn't happen for Wrapper classes. When I assign an Integer object to another, the operation simply behaves like we're dealing with values and not objects. As opposed to the above code, the output of the below code is 10:
Integer x = 10; //auto-boxed as new Integer(10)
Integer y = x;
x++;
System.out.printf("%d", y.intValue());
Why does this happen?
Do wrapper class objects get unboxed while being assigned to another object, so as to pass the value instead of the address??
When you do x++, it is the same as x = x + 1 so it is actually a new instance of Integer assigned to x but y still points to the old instance which value is 10.
Keep in mind that wrapper instances are immutable.
For an Integer x, the expression x++ can be understood like x = new Integer(x.intValue() + 1);. Its not exactly the same, but helps for understanding.
So, it doesn't modify the Integer object with the value 10 that x pointed to before the x++, it creates a new Integer object with the value 11 independent of the original 10 Integer, and assigns this 11 Integer to x.
But there's nothing in the x++ expression that would make y point to a different Integer instance. So y still points to the original 10.
That's the difference to the CLA example where you don't introduce a new instance with ob1.val++, but modify the single instance. If the Integer class had a public field value, then x.value++ would show the behaviour you expected - but the value field is (for good reason) private - not accessible to the outside.

Java overload confusion

java is not able to call any overload method as shown below :-
class LspTest{
public void add(int a, float b){
System.out.println("First add");
}
public void add(float a, int b){
System.out.println("second add");
}
public static void main(String [] a){
LspTest test = new LspTest();
test.add(1,1);
}
}
Please explain i am confused in this.
In your methods you are having parameters (int, float) and (float, int) but when calling the method you are passing both the int (1,1) values. The Java complier can auto type cast float to int whenever needed. But in this case compiler cannot decide auto type cast which int to float. Therefore it shows ambiguity.
You need to call it test.add(1f, 1); or test.add(1,1f); i.e. specify which value is int and which value is float.
P.S. To specify a value to be float you can write f with it.
When you initialise with literal values, in this case, compiler won't be able to infer the exact type. Therefore, it does not know which overload to call and returns the error that the reference to add is ambiguous. You can fix this by casting the arguments to the appropriate type, or even better, creating typed local variables initialised with 1 and passing the variables as parameters, like so:
int a = 1;
float b = 1;
LspTest test = new LspTest();
test.add(a,b);
There is an ambiguity here, and the Java compiler cannot figure out which method to call. Use test.add((float) 1, 1) or test.add(1, (float) 1) to explicitly tell which method you want.
This is the clear case of ambiguity which leads to a Compile Error.
Java compiler supports the type promotion. First of all, it'll checks for more specific data type if not match then it'll promote to next data type.
Java compiler will supports the type promotion in following order.
byte --> short --> int --> long --> float --> double
As your parameters (int,int) can be auto-promoted to float, java compiler can't decide in which one to invoke as both of your methods accepts the (1,1)

Wrapper class as method return type

Can someone please explain how/why is this allowed in Java?
public class Test {
private int text;
public Integer getText() {
return text;
}
I am basically having the wrapper class as the return type, while I am infact returning a primitive.
Because Java supports Autoboxing and Unboxing in versions 5 and up. That is an example of the former, but the later is equally important (and the reverse conversion). Per the link,
Autoboxing is the automatic conversion that the Java compiler makes between the primitive types and their corresponding object wrapper classes.
Consider the following code: (From: http://docs.oracle.com/javase/tutorial/java/data/autoboxing.html)
List<Integer> li = new ArrayList<>();
for (int i = 1; i < 50; i += 2)
li.add(i);
Although you add the int values as primitive types, rather than Integer objects, to li, the code compiles. Because li is a list of Integer objects, not a list of int values, you may wonder why the Java compiler does not issue a compile-time error. The compiler does not generate an error because it creates an Integer object from i and adds the object to li. Thus, the compiler converts the previous code to the following at runtime:
List<Integer> li = new ArrayList<>();
for (int i = 1; i < 50; i += 2)
li.add(Integer.valueOf(i));
Converting a primitive value (an int, for example) into an object of the corresponding wrapper class (Integer) is called autoboxing. The Java compiler applies autoboxing when a primitive value is:
Passed as a parameter to a method that expects an object of the corresponding wrapper class.
Assigned to a variable of the corresponding wrapper class.
From javadocs : Since java 5 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.
The java compiler applies autoboxing usually when -
Passed as a parameter to a method that expects an object of the
corresponding wrapper class.
Assigned to a variable of the corresponding wrapper class.
For the sake of performance, not everything in Java is an object. There are also primitives, such as int, long, float, double, etc.
For example java.lang.Integer class :-
It wraps an int.
Has two static final fields of type int: MIN_VALUE and MAX_VALUE.
MIN_VALUE contains the minimum possible value for an int (-2^31) and MAX_VALUE the maximum possible value for an int (2^31 - 1).
It also has two constructors - public Integer (int value) & public Integer (String value).
Integer has the no-arg byteValue, doubleValue, floatValue, intValue, longValue, and shortValue methods that convert the wrapped value to a byte, double, float, int, long, and short, respectively.
In addition, the toString method converts the value to a String.
Static methods parse a String to an int (parseInt) and convert an int to a String (toString).
class AutoBox {
public static void main(String args[]) {
// autobox an int
Integer a = 100;
// auto-unbox
int b = a;
System.out.println(b + " " + a); // displays 100 100
}
}
This feature has been added in Java 5.
text gets converted automatically into Integer by compiler. So basically its a syntactic sugar that can shorten your code (otherwise you would do conversions back and forth by yourself). Of course it has its price and if this happens a lot (I mean really a lot, big loops, frequent invocations and so forth), it can become a performance issue, so when using it, just remember the it happens under the hood and you'll be fine.
Integer.valueOf(text)
is called under the hood
The feature is called autoboxing btw
Hope this helps

What is the main difference between primitive type and wrapper class?

What is the difference between these two lines?
int pInt = 500;
and
Integer wInt = new Integer(pInt);
Or
Integer wInt = new Integer(500);
None.
That's the exact same thing. In the first case you just have a supplementary variable.
Note that with autoboxing you rarely need to have both an int and an Integer variables. So for most cases this would be enough :
int pInt = 500;
The main case where the Integer would be useful is to distinguish the case where the variable is not known (ie null) :
Integer i = null; // possible
int i = null; // not possible because only Object variables can be null
But don't keep two variables, one is enough.
In Java, an instance of a primitve class holds the actual value of the instance, but instance of a wrapper class holds a reference to the object. i.e. The address of the place where the object would be found.
When you write a program with this line:
Integer integer = 500;
The compiler changes it to this:
Integer integer = new Integer(500);
This process is called autoboxing. That is automatically putting a primitive-instance in a "box" of Integer. Hence, output of the following program:
public class PrimitiveToObject {
public static void main(String[] args) {
printClassName(1);
printClassName(1L);
printClassName((char)1);
}
public static void printClassName(Object object){
System.out.println(object.getClass());
}
}
is this:
class java.lang.Integer
class java.lang.Long
class java.lang.Character
Also this:
int i = integer;
changes into this:
int i = integer.intValue();
This is called unboxing.
As you can see above, the dot operator(.) is used on the variable named integer but not on i. That is: a wrapper's object can be dereferenced, but not a primitive instance.
Boxing and unboxing may slow down the program a little bit. Hence, to a newbie, wrappers may look like added burden, but they are not so. Wrappers are used at places where the object needs to be a reference type. eg: Map<Integer,String>map=new HashMap<Integer,String>(); is a valid statement, but Map<int,String>map=new HashMap<int,String>(); is not a valid statement.
Another typical case where wrapper is very useful: In MySQL, NULL is a valid entry for a column of INT type. But in Java, int cannot have a null value, Integer can. This is because in SQL NULL symbolises Not Available. So if you are using JDBC to insert integer values in a MySQL table, a null in your java program will help in inserting NULL in the MySQL table.
A wrapper class can also be useful in a case similar or anologous to this:
Boolean decision; // Using wrapper for boolean.
if("YES".equalsIgnoreCase(consent))
decision = Boolean.TRUE; // In favour
else if("NO".equalsIgnoreCase(consent))
decision = Boolean.FALSE; // Not in favour
else if("CAN'T SAY".equalsIgnoreCase(consent))
decision = null; // Undecided
For starters
int pInt = 500; , here pInt is not an object whereas in
Integer wInt = new Integer(500);
wInt is an reference
This is also a reason why java is not pure Object Oriented Language. Because everything is not object with java.
Wrapper class will have a box in that box it will cover the primitive data types there are 8 primitive data types namely byte,int ,long ,double, float, short ,Boolean ,char these all covered in wrapper class .
to use primitive data types we use like int a;
but to use wrapper class we need to use like Integer a = new Integer(i);
The types of data are the same, but there are situations that manipulation of objects is more convenient than primitive types, like data structures, where you need more control of your data types.
For example, objects can be null and primitive types can't.
You also can't call methods in a primitive type (.compareTo(), .equals(), ...), but in wrapper classes you can.
The information below describe the types in primitive and wrapper class:
Primitive Types | Wrapper Class (Superclass = Object)
boolean - Boolean
char - Character
Primitive Types | Wrapper Class (Superclass = Number)
byte - Byte
short - Short
int - Integer
long - Long
float - Float
double - Double
To understand how the wapper classes works, consider the example below:
public final class IntWrapper {
private final int intVal;
IntWrapper(int intVal) {
this.intVal = intVal;
}
public int getInt() {
return intVal;
}
}
Now we can make an object out of our new IntWrapper class and 'box' the primitive int value 41:
int i = 41;
IntWrapper iw = new IntWrapper( i ); // box the primitive int type value into the object
i = iw.getInt(); // unbox the value from the wrapper object
My example IntWrapper class is immutable, immutable means that once its state has been initialized its state cannot be changed.
When the final keyword is applied to a class, the final class cannot be extended. In other words, a final class can never be the superclass of a subclass. A final class can be the subclass of superclass, not problem there. When a class is marked final, all of its methods are implicitly final as well.
It is important to note that when final is applied to a reference variable it does not prevent the members of the object instance from changing values.
This example is to better understanding how the wrapper classes works inside.
Next, to create Integer, Double and other wrapper classes, you can write:
Integer i = new Integer(4);
Double d = new Double(9.62);
Boolean b = new Boolean("true");
Character c = new Character('M');
To get the encapsulated number into wrapper objects, you can write:
long l = i.longValue();
double e = i.doubleValue();
float f = d.floatValue();
short s = d.shortValue();
Each wrapper class include special methods to convert between primitive type to wrapper objects, that represent not number values:
boolean bo = b.booleanValue();
char ch = c.charValue();
Up to Java 5 version, the creation of objects from wrapper classes had to be in the syntaxes like above, but to simplify these operations, mainly related to insertion of values in the data structures offered in Java collections (that only accept objects), now exists the autoboxing or boxing and autounboxing or unboxing options.
The autoboxing or boxing allows you to insert a primitive value to reference of equivalent wrapper types or Object type:
// Same result of Double d = new Double(-2.75);
Double objD = -2.75;
// Same result of Object objI = new Integer(13);
Object objI = 13;
The autounboxing or unboxing allows you to insert a wrapper object into a variable of primitive type, converting automatically between equivalent types:
// Same result of double vd = objD.doubleValue();
double vd = objD;
// Same result of int vi = objI.intValue();
int vi = objI;
The most important practical difference I've seen is Integer is way more slower to initialize and do calculations with, than int. I would avoid Integer unless necessary.
int x = 20_000_000;// 20 millions
for (int i = 0; i < x; i++) {
ix += 23;
}
it takes 138 ms(average over 50 trials) to complete the loop when ix is an Integer but only takes 10 ms when ix is an int

In Java, what is the difference between the following declarations?

Considering Java. How are these 2 different and why?
public void languageChecks() {
Integer a = 5;
Integer b = new Integer(5);
change(a); // a doesn't get incremented. value is 5
change(b); // b does. value is now 6
}
public void change(Integer a) {
a++;
}
The only difference is that
Integer b = new Integer(5);
guarantees a new object is created. The first will use an instance from a cache (see Integer.valueOf()).
Both are immutable and the references to both are passed by value (as is everything in Java). So change() has no effect on either.
I'd always been taught a++ was just shorthand for a = a + 1 in which case a local variable is created named a and immediately thrown away when the method returns. There're no methods on Integer that change the value (it's immutable), and likewise no operations on primitive ints that change their value.
Neither call to change() affects the values passed in, because of auto-boxing/unboxing.
public void change(Integer a) {
// This unboxes 'a' into an int, increments it and throws it away
a++;
}
The above code seems to imply that a++ changes the value of a, since it's an object, not a primitive. However, ++ is not overloaded by Integer, so it unboxes it to be able to apply the ++operator on its int. To me the compiler shouldn't allow this.

Categories