文件流配合缓存机制可清晰揭示包装类缓存边界:通过 bufferedreader 读取数值并调用 integer.valueof(),真实触发 integercache 判断,使 -128~127 内 == 返回 true、之外返回 false,而 equals 始终为 true;float/double 无缓存,boolean 仅 valueof 复用常量。
直接用文件流配合缓存机制理解包装类比较,其实是个很巧妙的切入点——它把抽象的内存复用行为,转化成可观察、可验证的io过程。关键不在于“流”本身,而在于用流操作触发装箱行为,并通过缓存边界暴露 == 和 equals 的差异本质。
为什么文件流能帮你看清缓存边界
从文件读取数值(比如用 BufferedReader 读一行数字字符串,再 parse 成 int),再封装为包装类,这个过程天然规避了编译期常量优化。它迫使 JVM 在运行时走标准装箱路径:String → int → Integer.valueOf(int),从而真实触发 IntegerCache 的判断逻辑。不像 Integer a = 127 这种写法,可能被编译器和JVM联合优化,掩盖底层行为。
你可以把它看作一个“缓存探针”:每次读一个数、转一个包装类、存进集合或做比较,就能清晰看到 -128 ~ 127 内外的行为分水岭。
动手验证缓存边界的三步流式操作
-
准备测试数据文件(data.txt):每行一个整数,覆盖关键区间,例如:
127
128
-128
-129
0 -
用 BufferedReader + Integer.valueOf() 逐行加载:
不要用new Integer(),也不用自动装箱字面量(如Integer x = 127),确保走 valueOf 路径;
把每行生成的 Integer 对象存入 List 或 Map,便于后续比对。 -
用 == 和 equals 分别校验引用与值一致性:
对相同数值的两次读取结果(如两次读到 127),检查obj1 == obj2是否为 true;
对 128、-129 等越界值重复测试,会发现 == 返回 false,而 equals 始终为 true。
缓存机制在流场景下的真实表现
当你连续两次读取 "127" 并调用 Integer.valueOf(127),返回的是同一个对象地址 —— 因为 IntegerCache.cache[255](即 127 + 128)早已初始化完毕;但读取 "128" 时,valueOf 直接 new Integer(128),每次都是新堆对象,== 必然失败。
这种差异在日志解析、配置加载、CSV 表单导入等典型流式处理场景中极易踩坑。比如你用 Map
浮点型和 Boolean 的特殊提醒
别指望 Float/Double 有缓存 —— 它们的 valueOf 方法从不查缓存,每次都 new;所以 Float.valueOf(1.0f) == Float.valueOf(1.0f) 永远是 false。这不是 bug,是设计使然。
Boolean 看似简单,但要注意:只有 Boolean.valueOf("true") 和 Boolean.valueOf(true) 才复用 TRUE/FALSE 常量;而 new Boolean(true) 一定新建对象,== 比较必错。











