Integer and int duality?
Can someone explain me this
List<Integer> list = new LinkedList<Integer>();
list.add(2);
list.add(1);
list.add(3);
when I used
list.remove(1);
then 1st element got remove开发者_高级运维d
list.remove(new Integer("1"));
then 2nd element got removed.
so, can you explain behavior of auto boxing and unboxing in above senario
when new A().a(new Integer("1"));
executed on,
public class A {
public void test(Integer i) {} //1
public void test(int i) {} //2
public void test(Object o) {}//3
}
method 1 go executed
public class A {
public void test(int i) {} //2
public void test(Object o) {}//3
}
method 3 got executed
Basically overload resolution will prefer an Object
parameter over an int
parameter when presented with an Integer
argument. (It will prefer an overload with an int
parameter over Object
or Integer
when presented with an int
argument, of course.)
From JLS section 15.12.2 (with discussion snipped):
The process of determining applicability begins by determining the potentially applicable methods (§15.12.2.1). The remainder of the process is split into three phases.
Discussion
The purpose of the division into phases is to ensure compatibility with older versions of the Java programming language.
The first phase (§15.12.2.2) performs overload resolution without permitting boxing or unboxing conversion, or the use of variable arity method invocation. If no applicable method is found during this phase then processing continues to the second phase.
The second phase (§15.12.2.3) performs overload resolution while allowing boxing and unboxing, but still precludes the use of variable arity method invocation. If no applicable method is found during this phase then processing continues to the third phase.
The third phase (§15.12.2.4) allows overloading to be combined with variable arity methods, boxing and unboxing.
As Integer
is implicitly convertible to Object
, overload resolution succeeds in the first phase, so never gets as far as considering an unboxing conversion.
If that doesn't explain everything to your satisfaction, please comment on which bit remains puzzling for you.
list.remove(1);
here 1 is index, and not the object, so whatever object is present at index 1, will be deleted
list.remove(new Integer("1"));
Here its the object Integer(1), that will be deleted
This is all explained and specified in tha Java Language Specification.
The problem is that new Integer(2) is an object but 2 isn't
remove(1) removes the element with index 1
remove (new Integer(2) removes the Objecte equal to new Integer(2) (two different methods)
If you add(1) Java needs an object since there is no add(int) and performs Outboxing.
The same happens probably in your second example though it seems it got a little mixed up (text doesn't fit code).
The crucial part is: Unboxing of an Integer is only performed when an Integer can not be used, i.e. there is no use for Integer, Number or Object, but int can be used.
Overload resolution uses the best matching candidate. In the first case, you are passing Integer and there is a signature test(Integer) so that gets called (exact type match).
In the second case you pass Integer, and the two possible candidates are test(int) and test(Object). In this case the language defines the Object
upcast as a closer match than the int
unboxing, so the Object version is selected.
There is a list of overload resolution conversions here. As you can see, reference widening is higher up than unboxing.
From the Java language specification:
The first phase (§15.12.2.2) performs overload resolution without permitting boxing or unboxing conversion,
...
This guarantees that any calls that were valid in older versions of the language are not considered ambiguous as a result of the introduction of variable arity methods, implicit boxing and/or unboxing.
List
provides to methods:
public boolean remove(Object o) // removes the first occurence of this object
public boolean remove(int i) // removes object stored at index i
If we do a list.remove(new Integer(1))
then the best match for this call is the first method (remove the object).
There are two remove functions specified on a List:
- List.remove(int)
- List.remove(Object)
Although Java does perform autoboxing (and I believe it would, if the List.remove(int) method didn't exist), the idea here is determining which method to call. Since there is a valid operation with a primitive int
, that's going to be called before any autoboxing happens.
精彩评论