作者:Sicimike

blog.csdn.net/Baisitao_/article/details/92667122

前言

有时候写代码会遇到一些莫名其妙的问题,两个字符串明明toString()打印一模一样,但是equals就是为false。

问题

直接看代码

public static void main(String[] args) {String s1 = "hello‌world‌";String s2 = "helloworld";System.out.println(s1.equals(s2));
}

这代码应该够简单了,毫无疑问输出true啊。但是我们还是实际操作一下:

这是什么情况,居然输出了false,我多年的java白学了吗?

结论

其实这个问题很简单,因为字符串s1中包含了不可打印字符,可以把两个字符串复制到 QQ/TIM 看一下就知道了,或者直接按F12审查元素也可以看到。或者我们继续在Java代码中查看

public static void main(String[] args) {String s1 = "hello‌world‌";String s2 = "helloworld";System.out.println(s1.equals(s2));System.out.println(Arrays.toString(s1.getBytes()));System.out.println(Arrays.toString(s2.getBytes()));
}

这下应该很清楚的知道了为什么两个字符串toString()看起来一样,但是equals却为false。

不可见字符从哪来

说一个最常见的场景,window下新建一个test.txt文件(用window自带的记事本),随便写点什么,就“helloworld”吧。保存(另存为)的时候选择UTF-8编码。

这种方式保存的文件,window会在文件头部添加一个字符,叫做BOM(byte-order mark,字节顺序标记)以UTF-8编码时是三个字节,分别是EF BB BF,用来标记这是一个UTF8编码的文件。程序读取文件时,会把BOM头一起读入内存:

public static void compareContent() {InputStream is = null;try {is = new FileInputStream(new File("D:\\test.txt"));byte[] buff = new byte[16];int nRead = 0;StringBuilder sb = new StringBuilder();while ((nRead = is.read(buff)) != -1) {sb.append(new String(buff, 0, nRead));}//UTF-8文件读取的字符串String fileStr = sb.toString();//程序定义的字符串,此处不包含不可打印字符String localStr = "helloworld";System.out.println(fileStr.toString());System.out.println(localStr.toString());System.out.println("文件字符串:" + Arrays.toString(fileStr.getBytes()));System.out.println("本地字符串:" + Arrays.toString(localStr.getBytes()));} catch (IOException e) {e.printStackTrace();} finally {if (is != null) {try {is.close();} catch (IOException e) {e.printStackTrace();}}}}

运行结果如下:

除了前三个字节,后面的内容其实是一模一样的。

解决办法

如果文件非要以UTF-8编码保存,可以有以下几种方法:

  • 保存的时候去掉BOM头(notepad++支持以UTF-8无BOM格式编码

  • 程序做兼容,兼容代码如下:

public static String deleteUTF8Bom(String fileStr) {byte[] UTF8_BOM_BYTES = new byte[]{(byte) 0xEF, (byte) 0xBB, (byte) 0xBF};byte[] bytes = fileStr.getBytes();if (bytes[0] == UTF8_BOM_BYTES[0]&& bytes[1] == UTF8_BOM_BYTES[1]&& bytes[2] == UTF8_BOM_BYTES[2]) {return new String(bytes, 3, bytes.length - 3);}return fileStr;
}

总结

这个问题不太容易发现,但是其实也是属于基础内容。也说明眼见不一定为实,看到的字符串不一定就是真正的字符串。

  • @Autowire和@Resource注解使用的正确姿势,这些年我一直用错了!!

  • 华为面试官:为什么 HashMap 的加载因子是0.75?

  • 强大:MyBatis 流式查询

  • 华为面试官:为什么 HashMap 的加载因子是0.75?

  • SpringBoot+OAuth2+JWT实现单点登录SSO完整教程,竟如此简单优雅!

  • 趣头条面试题:ThreadLocal是什么?怎么用?为什么用它?有什么缺点

  • Springboot启动扩展点超详细总结,再也不怕面试官问了

  • 趣头条面试题:ThreadLocal是什么?怎么用?为什么用它?有什么缺点

  • List去除重复数据的五种方式,学到了...

  • SpringBoot操作ES进行各种高级查询(必须收藏)

点击阅读全文前往微服务电商教程

相同字符串,但是equals为false?我多年的java白学了吗?相关推荐

  1. 可怕!原来我们看到的世界地图一直都是“错”的!多年的地理白学了...

    ▲ 点击查看 几乎每个家庭都会有两张地图:一张世界地图,一张中国地图. 薄薄的两张纸,蕴藏着让每个人学会"看世界"的磅礴力量. 哈佛上一任校长,也是300多年来唯一一位女校长德鲁· ...

  2. 原来我们看到的世界地图竟这样震撼!多年的地理白学了...

    ▲ 点击查看 几乎每个家庭都会有两张地图:一张世界地图,一张中国地图. 薄薄的两张纸,蕴藏着让每个人学会"看世界"的磅礴力量. 哈佛上一任校长,也是300多年来唯一一位女校长德鲁· ...

  3. JAVA中String字符串比较equals()和equalsIgnoreCase()的区别

    标签: equals和equalsIgnoreC 2012-11-11 16:03 65644人阅读 评论(0) 收藏 举报  分类: JAVA(3)  1.使用equals( )方法比较两个字符串是 ...

  4. JAVA中字符串比较equals()和equalsIgnoreCase()的区别

    1.使用equals( )方法比较两个字符串是否相等.它具有如下的一般形式: boolean equals(Object str) 这里str是一个用来与调用字符串(String)对象做比较的字符串( ...

  5. java equals equalsignorecase 性能_JAVA中字符串比较equals()和equalsIgnoreCase()的区别

    JAVA中字符串比较equals()和equalsIgnoreCase()的区别 1.使用equals( )方法比较两个字符串是否相等.它具有如下的一般形式: boolean equals(Objec ...

  6. python中运行结果为false-python 两个一样的字符串用==结果为false问题的解决

    有时候我们需要判断两个字符串内容是否相等,判断内容相等,我们用"==",但是有时候发现print(str1)和print(str2)眼看着一模一样,但是用==时却是false 可能 ...

  7. python字符串equals方法_判断字符串相等-Equals(上)

    本次课程是零基础课程,只要熟悉计算机的基本应用和操作,一般可以完成本次课程学习.本课程深入浅出的介绍了C#语言的基本语法结构.条件选择.循环.异常处理.数组.集合.值类型和应用类型.字符串的常用方法. ...

  8. java学习中,字符串使用(比较、构造方法)(java 学习中的小记录)

    java学习中,字符串使用(比较.构造方法)(java 学习中的小记录)作者:王可利(Star·星星) String的使用 1.在内存中是如何保存字符串. == :比较的是地址(引用数据类型) equ ...

  9. Java从键盘输入n行字符串_Java十四天零基础入门-Java布尔类型

    不闲聊!!!不扯淡!!!小UP只分享Java相关的资源干货 Java布尔类型 在Java语言中布尔类型的值只包括true和false,没有其他值,不包括1和0,布尔类型的数据在开发中主要使用在逻辑判断 ...

最新文章

  1. mysql1401错误_mysql错误代号-I(1401~1450)
  2. 数组---进制转换(查表法)
  3. docker es持久化_Docker 搭建 ES 集群并整合 Spring Boot
  4. WordPress 常用快捷键列表
  5. 新SQL Server 2016示例数据库
  6. 揭开 Python 内存分配时的小秘密!
  7. Hadoop——Yarn(4)
  8. OC中方法与函数的区别
  9. 基于Matlab的hdb3编译码设计,基于MATLAB的HDB3编译码实现
  10. Radius协议简单介绍
  11. 实体连锁电商会员运营方案
  12. python中re模块的span_python3正则模块re的使用方法详解
  13. 联发科:上半年营收2980亿台币,下半年全面发力5G芯片,并布局6G
  14. 《近代名老中医经验集》出版
  15. D. Little Girl and Maximum XOR(贪心)
  16. Windows redis最新版本5.0.9下载
  17. RPA 的优点与缺点
  18. mininet构建双路由器实验
  19. 小程序直播,助力教育机构获客
  20. R语言ARIMA集成模型预测时间序列分析

热门文章

  1. 多媒体台式计算机各部分功能简介,计算机DIY基础知识
  2. 求数的最大值(重载)
  3. Pythom学习笔记
  4. 国产bi VS国外bi,谁更适合中国企业?
  5. [原创]DEDE 织梦建站,仿站(包含5套正版建站软件)
  6. 等保备案是等保测评吗?两者是什么关系?
  7. 四年级上册计算机课程内容,小学四年级上册信息技术教案3篇(人教版)
  8. Gensim:一款进行文本主题识别的 Python 工具库
  9. 鸿蒙os智能硬件论坛,华为终于公开了鸿蒙OS的野心!
  10. 1486_人月神话读书笔记_贯彻执行