游乐游手机版
首页/编程语言/文章详情

Java 中 String.getBytes() 返回不同结果的原因解析

时间:2026-04-29 20:46
Ja va 中 String getBytes() 返回不同结果的原因解析 String getBytes() 每次调用返回的是新创建的 byte[] 实例,其 toString() 默认输出为内存地址标识(如 [B@1b6d3586),因此看似“不同”;但数组内容完全一致,差异仅源于对象引用不同。

Ja va 中 String.getBytes() 返回不同结果的原因解析

Ja va 中 String.getBytes() 返回不同结果的原因解析

String.getBytes() 每次调用返回的是新创建的 byte[] 实例,其 toString() 默认输出为内存地址标识(如 [B@1b6d3586),因此看似“不同”;但数组内容完全一致,差异仅源于对象引用不同。

在 Ja va 开发中,你是否遇到过这样的场景:对同一个字符串连续调用 `getBytes()`,打印出来的结果却不一样?这看起来像是编码出了错,但实际上,这背后是一个关于 Ja va 对象模型的经典理解题。

简单来说,`String.getBytes()` 方法的作用,是将字符串按照默认字符集(通常是平台相关的 `Charset.defaultCharset()`,比如 UTF-8 或 GBK)编码成字节数组。关键在于,这个方法每次都会返回一个全新的 byte[] 对象。这意味着,即便对同一个字符串调用两次,你拿到手的也是两个内容一模一样,但“身份”完全不同的数组对象

来看一段典型的代码:

String key = "12345testabcd";
System.out.println(key.getBytes()); // 输出类似:[B@1b6d3586
System.out.println(key.getBytes()); // 输出类似:[B@2c7b84de

表面上看,`[B@1b6d3586` 和 `[B@2c7b84de` 截然不同。但真相是,这只是 `byte[].toString()` 方法在“捣鬼”。数组的 `toString()` 方法继承自 `Object` 类,其默认格式是“类名 + @ + 哈希码的十六进制表示”。这里的哈希码通常基于对象的内存地址生成。每个新数组对象都有自己独一无二的内存地址,因此哈希码自然不同——这仅仅标识了对象的“身份”差异,与数组内部的字节内容毫无关系

那么,如何正确地验证字节内容是否一致呢?诀窍在于使用正确的工具。

立即学习“Ja va免费学习笔记(深入)”;

import ja va.util.Arrays;
public class MainTest {
    public static void main(String[] args) {
        String key = "12345testabcd";
        byte[] bytes1 = key.getBytes();
        byte[] bytes2 = key.getBytes();
        System.out.println("Array 1: " + Arrays.toString(bytes1));
        System.out.println("Array 2: " + Arrays.toString(bytes2));
        System.out.println("Content equal? " + Arrays.equals(bytes1, bytes2)); // true
    }
}

使用 `Arrays.toString()` 可以直观地看到数组内容,而 `Arrays.equals()` 才是判断两个数组内容是否相等的“标准答案”。

✅ 几个重要的实践要点:

  • 显式指定编码:为了避免因平台默认字符集不同导致的潜在问题,推荐使用重载方法,如 `getBytes(StandardCharsets.UTF_8)`。
  • 不要依赖 `toString()`:永远记住,数组的 `toString()` 输出不是其内容的表示,不能用来判断数据是否相同。
  • 关注逻辑内容:在序列化、网络传输或加密等关键场景中,核心是字节数组的逻辑内容,而非承载它的那个对象引用本身。

总结一下,`getBytes()` 方法输出“不同”,这其实是一种视觉上的假象,根源在于 Ja va 中对象引用与对象内容的区分。深刻理解这一点,就能轻松避开这个常见的认知陷阱,写出更稳健的代码。

来源:https://www.php.cn/faq/2391733.html
上一篇怎么利用 Enum.valueOf() 结合 try-catch 稳健地处理不匹配的字符串枚举转换 下一篇如何在Debian上配置Python日志记录
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
列表遍历时动态判断阈值并返回相应文本
编程语言 · 2026-07-08

列表遍历时动态判断阈值并返回相应文本

遍历数值列表时,先筛选满足阈值的元素,再根据结果输出列表或友好提示。推荐使用列表推导式结合条件判断,注意边界用`>=`,空列表自动为假。也可用`any()`提前终止遍历,提升效率。此法简洁,避免显式循环,特别适合阈值筛选。

Maven项目中如何强制使用本地构建的依赖版本
编程语言 · 2026-07-08

Maven项目中如何强制使用本地构建的依赖版本

多模块开发中强制使用本地依赖的正确做法是使用-SNAPSHOT版本并配合`-U`参数强制更新,或重构为多模块项目统一管理生命周期。避免使用版本范围语法或手动复制JAR,确保构建行为可靠可重复。

Go语言net.Conn并发写安全与原子性保障解析
编程语言 · 2026-07-08

Go语言net.Conn并发写安全与原子性保障解析

Go标准库中net Conn支持并发方法调用,但Write()不保证原子性。多goroutine同时写入时,系统可能拆分数据包,导致内容交错,破坏消息边界。必须使用互斥锁或bufio Writer等显式同步机制确保写操作完整性,不可依赖系统调用本身的原子性。

Python在Windows系统中获取指定卷标U盘驱动器字母的方法
编程语言 · 2026-07-08

Python在Windows系统中获取指定卷标U盘驱动器字母的方法

使用Pythonwmi库通过Win32_Volume接口查询Windows系统中卷标为“TOSHIBA”的U盘盘符。需安装wmi和pywin32,注意大小写区分及多设备过滤。仅适用于Windows。

TP6.0消息已读功能基于Redis Bitmap未读计数方案
编程语言 · 2026-07-08

TP6.0消息已读功能基于Redis Bitmap未读计数方案

TP6 0中使用Redis位图实现消息已读标记,每条消息仅占一个比特,内存效率高。需将消息ID映射为连续偏移量,通过SETBIT和GETBIT操作。需提前维护用户ID到偏移量的映射表,注意键过期与驱动类型(phpredis与predis)问题。此方法内存极省,适合海量消息场景,且需确保偏移量唯一。