下面的代码运行结果是什么?解释一下为什么会有这些差异。

String s1 = "hello";
String s2 = s1 + ",world";
String s3 = "hello" + ",world";
String s4 = "hello,world";
String s5 = new String("hello,world"); System.out.println(s2.equals(s4)); // true
System.out.println(s2==s4);     // false
System.out.println(s3==s4);     // true
System.out.println(s4==s5);     // false

看似简单的代码,却有很多学问在里面。在此之前先非常简单地说一下JVM中的栈和堆,栈一般存放的是局部变量,对象的引用等;堆一般放对象、常量等,在 jdk1.7 以后的版本,字符串常量池也在堆中。

字符串常量池

  一般情况下,创建字符串对象有两种方式,一种是字面值创建,一种是 new 创建,这两者是不一样的。

  如果是字面值创建的方式,如 String s4="hello,world",JVM会先去字符串常量池中寻找有没有“hello,world”这个字符串,若有,则将其地址给 s4;若没有,则先在常量池里创建“hello,world”,然后再把地址给s4;而通过 new 的方式创建对象,则是在堆中创建“hello,world”对象,s5 指向这个对象。还是看图吧,比较直观:

  

equals() 和 ==

  这是 Java 面试常考点,有人可能会说 equals() 比较的是值,而 == 比较的是对象的引用(没错是我),直到被面试官吊打,才会老老实实去看 Object 类中 equals() 的源码:

 

  可以看到,equals() 方法体中,返回的是 两个对象的引用的比较结果 。但是,两个 String 类型 == 和 equals() 有时候结果却不一样。那是因为在 String 类中,equals() 被重写了:

  

  可以看到,它先对比两个引用;若一样则直接返回 true,不一样就对它们的值进行比较。因此,可以对 == 和 equals() 更好的区别了:

  

字符串的拼接

  String 类被 final 修饰,因此字符串不能修改,当两个字符串相加时,是先生成 StringBuilder 对象,然后通过 append() 的方式将两个字符串拼接,再调用 toString() 方法生成新的字符串对象。所以只考虑 s1 和 s2,他们在 JVM 中是这样的:

  

  但是像 String s3 = "hello" + ",world" 这样直接两个字面值相加的,java文件在编译期间就已经将这条语句做了优化,将其直接变成 "hello,world",等到运行的时候就查找字符串常量池,因此 s3 == s4 返回的结果就为 true。

String、StringBuilder、StringBuffer

  既然上面说到了 StringBuilder,那就顺便简单说一下这三者之间的区别。

  String 是常量,且每次需要在原来字符串基础上扩展都需要新建对象,导致速度会稍微慢一点,而且占内存,因此对于需要经常扩展的字符串,可以使用 StringBuilder 和 StringBuffer。但是 StringBuilder 和 StringBuffer 又有区别,即时两者很像,在速度上 StringBuilder 会快一些,因为 StringBuffer 的操作加了 synchronized ,即加了锁,使得操作相对比较慢,就举 append() 为例子,StringBuffer 中此方法的源码如下:

  

   所以,一般在单线程的情况下,可以选择使用 StringBuilder;在多线程的情况下可以选择 StringBuffer .

总结

  回到一开始的程序,我们可以大致地画出在 JVM 中的存储:

   

  

一段简单的关于字符串的 Java 代码竟考察了这么多东西的更多相关文章

  1. 使用非java代码编程

    使用非JAVA代码     JAVA语言及其标准API(应用程序编程接口)应付应用程序的编写已绰绰有余.但在某些情况下,还是必须使用非JAVA编码.例如,我们有时要访问操作系统的专用特性,与特殊的硬件 ...

  2. 基于Python使用SVM识别简单的字符验证码的完整代码开源分享

    关键字:Python,SVM,字符验证码,机器学习,验证码识别 1   概述 基于Python使用SVM识别简单的验证字符串的完整代码开源分享. 因为目前有了更厉害的新技术来解决这类问题了,但是本文作 ...

  3. Java将一段逗号分割的字符串转换成一个数组

    String 类:String 类代表字符串.Java 程序中的所有字符串字面值都作为此类的实例实现.字符串是常量,它们的值在创建之后不能更改.字符串缓冲区支持可变的字符串.因为 String 对象是 ...

  4. java基础面试题:如何把一段逗号分割的字符串转换成一个数组? String s = "a" +"b" + "c" + "d";生成几个对象?

    package com.swift; public class Douhao_String_Test { public static void main(String[] args) { /* * 如 ...

  5. Json字符串转换为java对象的各种实现方法【json_lib框架、Gson、org.json】

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://mengzhengbin520.blog.51cto.com/7590564/12 ...

  6. 使用eclipse开发Morphline的Java代码段

    背景:morphline是一个轻量级的etl工具.除了提供标准化的方法之外,还可以定制化的开发java片段.定制化的java片段会在加载时被作为一个独立的类编译,对源数据作处理. morphline关 ...

  7. 字符和字符串在Java中的旅程

    以下是个人对java中字符和字符串的见解,如有疏漏之处,还请不吝赐教. 下面通过一个简单的程序来说明字符和字符串在Java中的旅程. 以字符 ' 中 '为例, 它的GBK编码是2个字节:0xd6d0, ...

  8. 给定一个公式字符串用java进行拆解并计算结果

    需求很简单,给定一个字符串形式的公式规则,用java代码进行拆解,并能计算出结果. ♦考虑字符串中数字格式[整数.小数点] ♦考虑字符串中运算符[+-*/()] ♦考虑空格.运算规则[被0除] 以下是 ...

  9. XML字符串和JAVA对象之间的转化

     1.JAXB中相关的注解.类和接口说明 JAXB 中主要的一些注解 - shenyunsese 的专栏 - CSDN 博客 注:教程很全面很详细.但是仅供参考. 主要疑问区分和说明:  1.1 @X ...

随机推荐

  1. Android 8.1 自定义热点的时候设置了热点maxLength="32",但是在希伯来语等状态下还是发现在没到32个字符之前就无法把热点设置成功了

    初步认为应该是与热点名称的字节数有关. 然后开始查看源码. /Settings/res/xml/tether_prefs.xml 中的 <Preference android:key=" ...

  2. java的回调和C#的委托

    曾经有人对我说java的回调很巧妙. 今天我自己看了一下,回调的关键就是一个接口的事情. 也许是因为用了一定的手法,一开始不好懂吧,所以看懂了会感觉巧妙. 但是我心里的想法却是,真啰嗦! 回调的实例 ...

  3. 人生若只如初见---Spring概述以及环境的搭建

    Spring 是什么 Spring是由Apache开发的一种轻量型Java框架,能够更加便捷使用JavaBean(之前只有EJB才能实现) Spring的主要优势:分层架构: DAO层:(Data A ...

  4. Java架构师必知:什么是单点登录,主要会应用于哪些场景?

    单点登录在大型网站里使用得非常频繁,例如,阿里旗下有淘宝.天猫.支付宝,阿里巴巴,阿里妈妈,阿里妹妹等网站,还有背后的成百上千的子系统,用户一次操作或交易可能涉及到几十个子系统的协作,如果每个子系统都 ...

  5. 深入浅出Spring(二)

    IoC概念 控制反转(Inversion of Control)是一个重要的面向对象编程的法则来削减计算机程序的耦合问题. 它还有一个名字叫做依赖注入(Dependency Injection).Io ...

  6. Python用正则表达式匹配汉字

    Python用正则表达式匹配汉字 匹配多个汉字,不包括空格 import re res = re.match(r'[\u4E00-\u9FA5]+', '我是 汉字') print(res) # &l ...

  7. C# Properties文件夹 Bin 目录 Bin 目录

    Properties文件夹 定义你程序集的属性 项目属性文件夹 一般只有一个 AssemblyInfo.cs 类文件,用于保存程序集的信息,如名称,版本等,这些信息一般与项目属性面板中的数据对应,不需 ...

  8. 关于layer的基本所有的事件全部失效问题

    只要在页面中,要是存在id="undefined", layer的基本所有的事件全部失效. <input type="radio" id="un ...

  9. Yii2 负载均衡找不到JS,CSS

    在部署项目的时候,用了2台服务器.请求的时候用了负载均衡,导致 YII2 的静态文件(js,css...)报 404 ,原因是: 请求一个页面时 A服务器 去处理,但是静态资源缺请求到了 B服务器 , ...

  10. 关于Python中的错误与异常,你是否了解的够仔细?

    每次版本结束都描述这着同样的错误,相似的问题,但始终没见解决.所以今天,我就来总结下Python的错误与异常! 异常与错误 错误 语法错误 可以通过IDE或者解释器给出提示的错误 opentxt('a ...