先来看段代码
static boolean test(Integer a, Integer b) { return a == b; } public static void main(String[] args) { System. out.println( test(100, 100)); System. out.println( test(150, 150)); }
大家猜一下运行结果是什么?
test(100,100) 的输出结果为true,而 test(150,150)的输出结果是false。
这是为什么呢?嘿嘿,注意了,下面开始解密了。
首先我们确定一点,"==" 在java中比较对象时永远是比较对象的地址,这一点绝不会错,问题肯定出在 其他地方。分析一下test方法执行过程中到底发生了什么。因为test的参数是Integer 类型,所以调用test的时候会隐式地做一次装箱操作。
例如 执行test(100,100),首先会执行下面两句:Integer a = 100 ; Integer b = 100;然后在去执行方法体,比较 a 和 b 的地址是否是指向同一个对象。
首先我们确定一点,"==" 在java中比较对象时永远是比较对象的地址,这一点绝不会错,问题肯定出在 其他地方。分析一下test方法执行过程中到底发生了什么。因为test的参数是Integer 类型,所以调用test的时候会隐式地做一次装箱操作。
例如 执行test(100,100),首先会执行下面两句:Integer a = 100 ; Integer b = 100;然后在去执行方法体,比较 a 和 b 的地址是否是指向同一个对象。
由此看来,100 和 150 产生不同的结果,原因肯定出在自动装箱上。因为 == 过程就是比较对象地址,这个地址是在自动装箱时赋值的。那么自动装箱时到底发生了什么呢?
IntegerCache看名字我们就知道,这个肯定是和缓存相关的,看一下源码也知道这个内部类确实是用来缓存Integer值的。默认缓存的Integer 值范围是 -128 ~ 127 。
public static Integer valueOf(int i) { if(i >= -128 && i <= IntegerCache.high) return IntegerCache.cache[i + 128]; else return new Integer(i); }
IntegerCache看名字我们就知道,这个肯定是和缓存相关的,看一下源码也知道这个内部类确实是用来缓存Integer值的。默认缓存的Integer 值范围是 -128 ~ 127 。
我们来分析一下valueOf(int i)的执行过程:如果 i 大于缓存中的 最小值(-127) 并且 小于 缓存中的最大值(127),直接返回IntegerCache 中缓存的Integer对象。否则就新建一个Integer对象并返回。
这下100 和 150 的区别就了然了吧。test(100,100)时,两次装箱操作后,a 和 b 都是指向缓存中的同一个对象,当然是返回true了。test(150,150) 就不一样了,装箱操作时都是返回新的Integer对象,== 操作时地址必然不相等,所以返回false。
所以以后遇到数字比较时,要么先将值赋给对应的基本类型在比较,要么比较包装类型中的包装值(例如 a.intValue() == b.intValue()),要么直接调用equals方法
另外在Byte、Character、Short和Long中都有内部类,其中都提供了缓存!
相关推荐
题目中提到的"血案"实际上是一个关于`Integer`对象相等性比较的陷阱。在Java中,`Integer i01 = 59`这样的语句会触发装箱操作,将`int`值59转换为`Integer`对象。当进行`i01 == i02`的比较时,如果`i02`是一个`int`...
Java中的自动装箱和拆箱是自JDK 1.5版本引入的一种语言特性,它极大地简化了基础数据类型(如int)与它们对应的包装类(如Integer)之间的转换过程。这一特性使得开发者无需手动创建包装类实例或使用显式类型转换,...
这个特性在提高编程效率的同时,也可能带来一些隐藏的陷阱,尤其是在性能敏感的代码中。本篇文章将深入探讨Java中的自动装箱,并分析可能遇到的问题。 自动装箱是指Java编译器自动将基本数据类型(如int、char、...
在Java编程语言中,面试时常会遇到关于Integer与int之间区别的问题,这些问题是考察开发者对数据类型、内存管理和自动装箱拆箱的理解。...在今后的面试中,你可以自信地回答这些问题,避免掉入常见的陷阱。
根据`Integer`类的设计,对于-128到127之间的整数值,`Integer.valueOf`方法会从缓存中返回相同的`Integer`实例。这意味着在这个范围内,对于相同值的`Integer`对象,使用`==`操作符比较将返回`true`。但是,如果...
在Java编程中,即便是经验丰富的开发人员也难免会遇到一些常见的陷阱和误区。本文将深入探讨这些易错点,帮助开发者更好地理解这些问题,并学会如何避免它们。 #### 1. 类加载问题 Java类加载机制是Java运行时环境...
Java Integer类和int是Java中两个相关却又不同的概念,很多开发者容易混淆它们之间的区别本文将通过实例来了解Java Integer类和int的区别。 知识点1:自动装箱和拆箱 在Java中,我们可以直接声明Integer i = 10,...
在Delphi中,使用接口可以实现很多灵活的功能,但也存在一些陷阱。第一个陷阱与接口的类型转换有关。 1. **不能把一个对象引用强制转换成这个引用的类型没有声明实现的接口**: - 举例说明: ```delphi I1 = ...
如果值在缓存范围内(-128到127),则会从IntegerCache中获取或复用已存在的对象,否则新建一个对象。 拆箱则是通过调用包装器类的特定Value方法,如Integer的intValue(),Double的doubleValue()等,将包装器对象...
Java Puzzlers是Java编程中的一系列巧妙问题,旨在揭示语言中的陷阱、误导性和意外行为。这些谜题通常由简单的代码片段构成,看似无害,但执行结果却往往出乎意料。通过解决这些Puzzlers,开发者可以增强对Java语言...
"gotcha"一词通常用来形容编程语言中的易犯错误或陷阱,这些错误往往由于其看似简单的使用方式而诱使程序员误入歧途,但结果却出乎意料且不合理。在Verilog和SystemVerilog中,也有许多这样的陷阱,这需要工程师们对...
Java 自动转换是Java编程语言中的一个重要特性,它涉及到类型转换、自动装箱与拆箱、数据类型提升等多个方面。...在实际编程中,应灵活运用这些转换规则,同时注意潜在的陷阱和异常处理,确保程序的健壮性。
"Java SCJP 陷阱大全"显然是一份集合了Java编程中常见错误、陷阱和难点的资料,旨在帮助考生或者开发者避免在实际工作中遇到这些问题。以下将详细介绍Java SCJP考试中的一些关键知识点和常见陷阱: 1. **基本语法**...
下面我们就来深入探讨一下Java中常见的陷阱及其解决方案。 1. **找奇数的陷阱** ```java public static boolean isOdd(int i){ return i % 2 == 1; } ``` 这段代码用来判断一个整数是否为奇数,但存在一个...
Java中也有包装类,如`Integer`、`Double`等,它们用于封装基本数据类型。包装类的对象也存储在堆中,其引用存储在栈中。例如: ```java Integer a = 100; // 实际上是 new Integer(100) ``` **2.4 String类型数据...
例如,`Integer.parseInt()`方法将字符串转换为整数,`Object.toString()`方法将对象转换为字符串。 5. 数组类型转换 当数组的元素类型不匹配时,可以通过数组拷贝的方式进行类型转换。例如,从Object[]转换为...
`typedef` 在 C 语言中是一个非常有用的工具,它提供了定义类型别名的功能,从而让代码更加易读、可维护,特别是在处理复杂类型或者跨平台编程时。下面将详细阐述 `typedef` 的四个主要用途以及两个需要注意的陷阱。...
在JDK5.0之前,Java中的原始类型(如int)与它们对应的包装类(如Integer)之间需要手动进行转换。JDK5.0引入了自动封箱和自动解封机制,使得开发者在使用过程中可以更加方便地处理这两种类型之间的转换。例如,`...
### 审查Java代码的十一种常见...以上四个案例覆盖了Java编程中常见的几个陷阱,通过遵循最佳实践和了解语言特性,可以有效地避免这些问题,提高代码质量。接下来的几节将继续介绍更多常见的Java代码错误及其解决方法。
- **字符串转换为基本数值类型**:使用包装类提供的静态方法,如`Integer.parseInt(String s)`。 **7.6 包装类与方法重载** - 包装类可以作为方法参数参与方法重载。 **7.7 Long型、Float型和Double型包装类对象...