Java no autoboxing for int for compareTo method? - java

class Test{
public static void main(String[] args){
int a = 1;
int b = 5;
Integer c = new Integer(1);
Integer d = 5; //autoboxing at work
System.out.println(c.compareTo(d));
System.out.println(a.compareTo(b));
}
}
Why doesn't a.compareTo(b) compile (int cannot be dereferenced)? I know that compareTo requires objects, but I thought autoboxing would automatically make an int an Integer when necessary. Why doesn't autoboxing occur in this case? And what other cases will it not occur?

From the Oracle tutorial on Autoboxing, the two cases where boxing will occur are, when primitives are:
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.
The expression being evaluated in your example (a.compareTo(d)) does not fall in any one of those scenarios.
Theres some interesting additional information in the JCP proposal for autoboxing, describing the mechanics and rules for assignment conversion, method invocation conversion, and casting conversion.

Related

Why does the assignment of a short variable to an Integer reference produce a compile time error?

I have the following code in Java :
class Boxing
{
public static void main(String args[])
{
short s = 10;
Integer iRef = s;
}
}
Why does it produce an error in compilation? If I explicitly typecast the short to an integer in the expression, it compiles successfully. Since I'm using a short in an expression isn't the type of that supposed to be an integer by default without requiring the explicit case?
You want to have two things happening here: widening and auto-boxing.
Unfortunately, Java does only one of the two automatically. The reason for that is most likely that autoboxing was introduced fairly late (in Java5), and they had to be careful to not break existing code.
You can do
int is = s; // widening
Short sRef = s; // autoboxing
Integer iRef = (int) s; // explicit widening, then autoboxing
Here´s the documentation from JLS 5.1.7
Boxing conversion converts expressions of primitive type to corresponding expressions of reference type. Specifically, the following nine conversions are called the boxing conversions:
From type boolean to type Boolean
From type byte to type Byte
From type short to type Short
From type char to type Character
From type int to type Integer
From type long to type Long
From type float to type Float
From type double to type Double
From the null type to the null type
Basicly the direct conversion from short to Integer is not part of the autoboxing process of Java.
The autoboxing, as provided above, is only able to implicity cast the representing primitive type to it´s representing Wrapper class. Since this is not the case it will cause a compile time error.
Boxing conversion converts expressions of primitive type to corresponding expressions of reference type. Specifically, the following nine conversions are called the boxing conversions:
From type boolean to type Boolean
From type byte to type Byte
From type short to type Short
From type char to type Character
From type int to type Integer
From type long to type Long
From type float to type Float
From type double to type Double
From the null type to the null type
Reference: Conversions and Promotions Reference
In the code considered.
class Boxing
{
public static void main(String args[])
{
short s = 10;
Integer iRef = s;
}
}
Integer extends java.lang.Number. And java.lang.Short also extends java.lang.Number. But Short and Integer are not directly related if you wanted you can run the following program.
class Boxing
{
public static void main(String args[])
{
short s = 10;
Number iRef = s;
}
}
It will run without producing any error.
Java attempts to perform auto-widening, then auto-boxing, then auto-upcasting, but will not perform two of these for the same assignment. This is explained and diagrammed here, for the related case of method parameter assignment.

why is increment in reference of integer class object manipulates integer value?

I have a basic doubt, we can increment reference of Integer class object, while not reference of any other class(D class has 1 Integer data member and one parameterized constructor).
Integer x=new Integer(10); x++;
D d=new D(10); d++;
here both x and d are reference still we are able to increment Integer reference while not any other reference. I am missing something very basic, please help me out.
Integer x=new Integer(10); x++;
Here java compiler will do the un-boxing of the object, which converting the Integer object into primitive int. Then the increment operation will be performed. This is only defied for java primitives, the auto-boxing is converting primitive to wrapper object and reverse of it is call un-boxing. This is what is happening here.
The auto-boxing or un-boxing which is an automatic conversion, it is defined for java primitives only. So it can not be performed on other objects. Remember, the object are not just memory references like C or C++ that we can increment them.
This is because of Autoboxing for wrapper classes which was introduced from jdk 1.5. Internally java will convert the integer reference to int and increment it. You can't increment the objects.
Java has no way of overloading operators for arbitrary classes. Thus, D d; d++ is just not available. You can do:
public class D {
private int value;
public D( int v ){
value = v;
}
public void increment(){
value++;
}
}
Now you can do
D d = new D(10);
d.increment();
and d's value will be 11.
According to Oracle Java Documentation, The automatic conversion of primitive data types into its equivalent wrapper type is known as autoboxing and opposite operation is known as unboxing. Whenever we use object of wrapper class in an expression, automatic unboxing and autoboxing is done by JVM.
Integer object;
object = 100; //Autoboxing of int
++object;
When we perform an increment operation on Integer object, it is first unboxed, then incremented and then again reboxed into Integer type object. You can also take a look at How java auto boxing/unboxing works?

final casting concept doesn't apply for overloading

In my casting class, teacher taught us an interesting fact as follows.
class Casting {
public static void main(String args[]){
int i = 10;
byte b = i;
System.out.println(b);
}
}
We got an error
java:5: possible loss of precision
And then we changed the code as follows
class Casting1 {
public static void main(String args[]){
final int i = 10;
byte b = i;
System.out.println(10);
}
}
10
We got the correct output. As for the reason, he told that when we modify a variable final the variable is stored in the smallest data type possible. In this case was a byte. That's the reason that we were able to cast that without using the cast keyword.
But when we use method overloading like this,
class A {
void m(int i){
System.out.println("int");
}
void m(byte b){
System.out.println("byte");
}
public static void main(String args[]){
A a1 = new A();
final int i = 10;
a1.m(i);
}
}
I get the output int. If the final variables are stored in the lowest possible data type, it should be byte. So I tried the following code without overloading.
class A {
void m(byte b){
System.out.println("byte");
}
public static void main(String args[]){
A a1 = new A();
final int i = 10;
a1.m(i);
}
}
java:9: m(byte) in A cannot be applied to (int)
What's the reason for this? Is there any point that I have misunderstood?
You are mixing up memory space of variables and their type.
Calling the method m(...) will first of all check the type of the paramether variable. Here it is an int so it will chose the according overloaded method, no matter the size of the int in memory.
Although I really apreciate you first example that brings the light into one of the characteristics of the final identifier.
This bit isn't quite correct...
"As for the reason, he told that when we modify a variable final the variable is stored in the smallest data type possible. In this case was a byte."
It doesn;t store it as a byte, it stores it as an int, BUT it is effectively a constant so when Java compiles the line byte b = i; it knows for sure that the value will be 10, which doesn't need casting.
Is there any point that I have misunderstood?
Yes. The search for which method to apply depends on the types of the arguments. Unlike the case of assignments, there's no conversion attempt for method arguments (at least, there wasn't before autoboxing was added to the language, which adds another set of arbitrary rules).
If the conversion is part of an assignment, and the value can fit into a byte, the compiler performs the conversion automatically for you.
The JLS clearly explains that is a special case that only applies to assignment and not to conversions in other contexts.
It's worth mentioning that byte is useful only when you program for embedded devices or dealing with files/networks. byte and int occupy the same space because variables addresses are aligned.

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

Categories