有人可以解释一下这个
List<Integer> list = new LinkedList<Integer>();
list.add(2);
list.add(1);
list.add(3);
当我使用
时 list.remove(1);
然后第一个元素被删除
list.remove(new Integer("1"));
然后第二个元素被移除。
所以,你能解释上面的Senario中自动装箱和拆箱的行为吗?
new A().a(new Integer("1"));
执行,
public class A {
public void test(Integer i) {} //1
public void test(int i) {} //2
public void test(Object o) {}//3
}
方法1执行
public class A {
public void test(int i) {} //2
public void test(Object o) {}//3
}
方法3已执行
答案 0 :(得分:2)
基本上,当出现Object
参数时,重载决策将优先于int
参数而不是Integer
参数。 (当然,当出现int
参数时,它会偏好Object
参数超过Integer
或int
。)
来自JLS section 15.12.2(讨论已删除):
确定适用性的过程首先确定可能适用的方法(§15.12.2.1)。该过程的其余部分分为三个阶段。
讨论
分阶段的目的是确保与旧版本的Java编程语言兼容。
第一阶段(§15.12.2.2)执行重载解析而不允许装箱或拆箱转换,或使用变量arity方法调用。如果在此阶段没有找到适用的方法,则处理继续到第二阶段。
第二阶段(§15.12.2.3)在允许装箱和拆箱的同时执行重载解析,但仍然排除使用变量arity方法调用。如果在此阶段没有找到适用的方法,则处理继续到第三阶段。
第三阶段(§15.12.2.4)允许重载与变量arity方法,装箱和拆箱相结合。
由于Integer
可隐式转换为Object
,因此重载解析在第一阶段成功,因此从未考虑到取消装箱转换。
如果这并不能解释您满意的一切,请评论哪一点仍然令您感到困惑。
答案 1 :(得分:1)
list.remove(1);
此处1是索引,而不是对象,因此索引1处的任何对象都将被删除
list.remove(new Integer("1"));
这里是对象Integer(1),将被删除
答案 2 :(得分:0)
这一切都在Java Language Specification中解释和指定。
答案 3 :(得分:0)
问题是新的Integer(2)是一个对象但是2不是
remove(1)删除索引为1的元素
remove(new Integer(2)删除Objecte等于new Integer(2)(两种不同的方法)
如果添加(1)Java需要一个对象,因为没有add(int)并执行Outboxing。
同样的情况可能发生在你的第二个例子中,虽然它看起来有点混乱(文本不适合代码)。
关键部分是:只有在不能使用Integer时才会执行Intebox的Unboxing,即不使用Integer,Number或Object,但可以使用int。
答案 4 :(得分:0)
重载分辨率使用最佳匹配候选。在第一种情况下,您传递的是Integer,并且有一个签名测试(Integer),以便调用(精确类型匹配)。
在第二种情况下,您传递Integer,两个可能的候选者是test(int)和test(Object)。在这种情况下,语言将Object
upcast定义为比int
拆箱更接近的匹配,因此选择了Object版本。
有一个重载决策转换列表here。如您所见,参考扩展比拆箱更高。
答案 5 :(得分:0)
来自Java language specification:
第一阶段(§15.12.2.2)执行 不允许的重载决议 装箱或拆箱转换,
...
这可以保证任何调用 在旧版本中有效 语言不被认为是模棱两可的 由于引入 变量arity方法,隐含 装箱和/或拆箱。
答案 6 :(得分:0)
List
提供方法:
public boolean remove(Object o) // removes the first occurence of this object
public boolean remove(int i) // removes object stored at index i
如果我们执行list.remove(new Integer(1))
,则此调用的最佳匹配是第一种方法(删除对象)。
答案 7 :(得分:0)
List上指定了两个删除函数:
尽管Java确实执行了自动装箱(我相信如果List.remove(int)方法不存在),这里的想法是确定调用哪种方法。由于存在基元int
的有效操作,因此在任何自动装箱发生之前都会调用它。