我想知道下一个代码片段的内部Java行为是什么:
Long a = 123L;
long b = 123;
System.out.println("a equals b?: " + (a == b));
结果为true
,但比较两个Long
个对象将是false
(因为它会比较它们的引用)。是Java将Long
对象转换为其原始值,因为检测==
运算符是否与另一个原始对象相对应?
答案 0 :(得分:5)
Java是否将Long对象转换为其原始值,因为检测到== operator对另一个原始对象?
是。其中一个操作数是基本类型,另一个操作数可以通过拆箱转换为基元。
JLS section 15.21.1说(强调我的):
如果等于运算符的操作数都是数字类型,或者一个是数字类型而另一个是可转换的(第5.1.8节)是数字类型,则对操作数执行二进制数字提升(第5.6.2节) )。
请注意,二进制数字促销执行值集转换(第5.113节),可执行拆箱转换(第5.1.8节)。
此外,重要的是要注意,仅当两个操作数都是对象时才执行引用相等性。 JLS section 15.21.3说:
如果等于运算符的操作数既是引用类型又是null类型,则操作是对象相等。
答案 1 :(得分:2)
自动装箱和拆箱
Autoboxing是Java编译器自动转换 原始类型与其对应的对象包装器之间 类。例如,将int转换为Integer,将double转换为a 双,等等。如果转换是另一种方式,那就是 称为拆箱。
以下是自动装箱的最简单示例:
Character ch = 'a';
本节中的其余示例使用泛型。如果你不是 但是熟悉泛型的语法,请参阅泛型(更新) 教训。
请考虑以下代码:
List<Integer> li = new ArrayList<>(); for (int i = 1; i < 50; i += 2) li.add(i);
虽然您将int值添加为基本类型,而不是 整数对象,li,代码编译。因为li是一个列表 整数对象,不是int值列表,你可能想知道为什么是Java 编译器不会发出编译时错误。编译器没有 生成错误,因为它从i创建一个Integer对象并添加 李的对象。因此,编译器将先前的代码转换为 在运行时跟随:
List<Integer> li = new ArrayList<>(); for (int i = 1; i < 50; i += 2) li.add(Integer.valueOf(i));
将原始值(例如int)转换为对象 相应的包装类(Integer)称为autoboxing。该 当原始值为:
时,Java编译器应用自动装箱
- 作为参数传递给期望对象的方法 相应的包装类。
分配给的变量 相应的包装类。 请考虑以下方法:
public static int sumEven(List li){ int sum = 0; for(整数i:li) if(i%2 == 0) sum + = i; 回报; }
因为余数(%)和一元加(+ =)运算符不适用 对于Integer对象,您可能想知道为什么Java编译器会编译它 方法没有发出任何错误。编译器不生成 错误,因为它调用intValue方法将Integer转换为 运行时的int:
public static int sumEven(List<Integer> li) { int sum = 0; for (Integer i : li) if (i.intValue() % 2 == 0) sum += i.intValue(); return sum; }
将包装类型(Integer)的对象转换为其对应的 primitive(int)值称为unboxing。 Java编译器适用 当包装类的对象是:
时取消装箱
- 作为参数传递给期望相应基元类型值的方法。
- 分配给相应基元类型的变量。