点击蓝色“程序猿DD”关注我

回复“资源”获取独家整理的学习资料!

作者:tan日拱一兵

来源:公众号「日拱一兵」

关于 Java String,这是面试的基础,但是还有很多童鞋不能说清楚,所以本文将简单而又透彻的说明一下那个让你迷惑的 String

在 Java 中,我们有两种方式创建一个字符串

String x = "abc";String y = new String("abc");

你常见也常写第一种,很少见第二种,但面试还总问这类问题,双引号和构造器两种形式创建字符串到底有什么差别呢?

先来看例子

例子 1

String a = "abcd";String b = "abcd";System.out.println(a == b);  // TrueSystem.out.println(a.equals(b)); // True

a == b 结果为 true,是因为 a 和 b 都指向 方法区(method area) 同一个字符串文字,内存引用是同一个

当多次创建相同的字符串文字时,只存储每个不同字符串值的一个副本。这个叫做字符串留驻/留用,Java 中所有编译期字符串常量都会被自动留驻

例子 2

String c = new String("abcd");String d = new String("abcd");System.out.println(c == d);  // FalseSystem.out.println(c.equals(d)); // True

c==d 结果为 false,因为 c 和 d 的引用指向中不同的对象,不同的对象肯定有不同的内存引用

举了两个例子,文字描述有点懵?我们来试图通过图形来理解上述两种情况:

也许你已经看看出来了,一个是在方法区,一个是在中,在 JVM 模型中这是两个不同的区域,也许你面试时也经常被问到吧,来看下图:

再次提醒一下,所有 new 的对象都会在 Heap 中,这样以后你就好区分了

运行期字符串留驻

上面说的字符串留驻是在编译期,那么运行期可以吗?答案是肯定的,我们需要一个函数来帮忙

String c = new String("abcd").intern();String d = new String("abcd").intern();System.out.println(c == d);  // Now trueSystem.out.println(c.equals(d)); // True

看到 c == d 结果为 true,你应该理解 intern (英文有拘留,软禁的意思)的作用了,通过调用 intern()方法,就好比把创建的字符串拘留在方法区一样了

在面试时甚至还会问你下面代码创建了几个对象:

String d = new String("abcd")

  1. 如果方法区已存在"abcd", 那么只创建一个 new String 的对象

  2. 如果方法区没有"abcd", 那么要创建两个对象,一个在方法区,一个在堆中

所以,正常情况下我们没必要使用构造器创建对象,因为这很可能会产生一个额外的没用的对象,但是有例外哦,我们下面说

String s = "abcd";s = s.concat("ef");

当我们想在字符串 s 后面拼接字符"ef"时,会在堆中创建一个新的对象,并将 s 的引用指向新创建的对象,由于 String 创建的是不可变对象,所以 String 类中的所有方法都不会改变它自身,而是返回一个新的字符串(快打开你的 IDE,看看是否每个操作String 的方法最后都是返回有 return new String 字样),到这里你也应该理解了一个道理:

如果我们需要一个字符串被修改,我们最好使用 StringBuffer 或者 StringBuilder,否则,由于每次操作字符串都会创建一个新的对象,而旧的对象不会有引用指向它,这样我们会浪费很多垃圾回收的时间

到这里还没完,你有没有想过为什么 String 会被设置/制造成 final?

为什么 String 类被 final 修饰

字符串池的需求

字符串池(String intern pool)是方法区域中的一个特殊存储区域。当创建一个字符串时,如果该字符串已经存在于池中,那么返回现有字符串的引用,而不是创建一个新对象。所以说,如果一个字符串是可变的,那么改变一个引用的值,将导致原本指向该值的引用获取到错误的值

缓存 hashcode

字符串的hashcode在Java中经常使用。例如,在HashMap或HashSet中。不可变保证hashcode始终是相同的,这样就可以在不担心更改的情况下兑现它。这意味着,不需要每次使用hashcode时都计算它。这样更有效率。所以你会在 String 类中看到下面的成员变量的定义:

/** Cache the hash code for the string */private int hash; // Default to 0

安全性

String被广泛用作许多java类的参数,例如网络连接、打开文件等。如果字符串不是不可变的,连接或文件将被更改,这可能导致严重的安全威胁。该方法认为它连接到一台机器上,但实际上并没有。可变字符串也可能导致反射中的安全问题,因为参数是字符串

不可变对象天生是线程安全的

由于不可变对象不能被更改,所以它们可以在多个线程之间自由共享。这消除了同步的需求。

总之,出于效率和安全性的考虑,String 被设计为不可变的。这也是为什么在一般情况下,不可变类是首选的原因。

附加说明

关于不可变对象和不可变引用总是有同学搞不清楚

final User user = new User();

上面的代码指的是 user 引用不能被更改指向内存的其他地址,但是由于 User 是可变对象,我们可以调用 user 的 setter 方法修改其属性
在String类中包含很多学问,包括你对JVM模型的理解,这也就是为什么面试官为什么喜欢问String,主要考察你的基本功

灵魂追问

  1. String 和基本类型的包装类如 Integer 和 Long 都被 final 修饰,但为什么不建议作为 synchronized 同步块的参数使用呢?

  2. 基本类型自动装箱你知道发生了什么吗?

推荐关注:日拱一兵

简介:以读侦探小说思维轻松趣味学习 Java 技术栈相关知识,本着将复杂问题简单化,抽象问题具体化和图形化原则逐步分解技术问题,技术持续更新,请持续关注!

留言交流不过瘾?添加微信:zyc_enjoy

根据指引加入各种主题讨论群

  • 阿里程序员推荐的15 款常用开发者工具

  • 一文学会Maven私服的搭建

  • 真实的上海IT圈:张江男vs漕河泾男

  • IntelliJ IDEA 2019 快捷键终极大全,速度收藏!

  • Java 程序员常用的 22 个Linux命令


点一点“阅读原文”小惊喜在等你

为什么面试官总喜欢问String?相关推荐

  1. 为什么程序员面试官总喜欢问你有什么技术亮点?

    我们要回答这个问题,首先得知道什么算是亮点?在百度百科上解释的亮点是:比喻有光彩而引人注目的人或者事务.比如说一个旧书拍卖会上,带有作者亲笔签名的书籍是本次拍卖会上的亮点.所以简单来说,亮点和闪光点是 ...

  2. HDFS读写流程(重点,有些面试官总喜欢问到,记录一下)

    写数据流程 ①服务端启动HDFS中的NN和DN进程 ②客户端创建一个分布式文件系统客户端,由客户端向NN发送请求,请求上传文件 ③NN处理请求,检查客户端是否有权限上传,路径是否合法等 ④检查通过,N ...

  3. 面试java你最擅长什么_面试官最喜欢问的10道Java面试题

    1.Java的HashMap是如何工作的? HashMap是一个针对数据结构的键值,每个键都会有相应的值,关键是识别这样的值. HashMap 基于 hashing 原理,我们通过 put ()和 g ...

  4. 今天来谈谈面试官最喜欢问JS中的闭包问题吧

    今天来谈谈面试官最喜欢问JS中的闭包问题吧 1.什么是闭包? 闭包是指有权访问另外一个函数作用域中的变量的函数,闭包就是函数的局部变量集合,只是这些局部变量在函数返回后会继续存在.闭包就是函数的&qu ...

  5. 阿里的面试官都喜欢问哪些问题?

    作者:徐刘根 | 公众号:Java之间 金九银十是招聘的旺季,小编在这里也给大家整理了一套阿里面试官最喜欢问的问题或者出场率较高的面试题,助校招或者社招路上的你一臂之力! 首先我们需要明白一个事实,招 ...

  6. 求职Python开发,面试官最喜欢问的几个问题

    关注公众号「Python专栏」,后台回复:简历模板,获取给大家准备的价值99元的程序员简历模版11份. ![Python专栏二维码](https://img-blog.csdnimg.cn/20190 ...

  7. Python | 面试官最喜欢问的几个问题

    0. 概述 Python是个非常受欢迎的编程语言,随着近些年机器学习.云计算等技术的发展,Python的职位需求越来越高.下面我收集了一些Python面试官经常问的问题,供大家参考学习. 1. 类继承 ...

  8. 面试官超级喜欢问的JVM

    前言 随着阿巴阿巴在面试中愈战愈勇,这几天又约上面试了,这次面试官让她谈谈对JVM的理解. 回家等通知 面试官: 你对JVM的内存模型了解吗?能否讲讲里面的细节呢? 阿巴阿巴: JAVA虚拟机在执行J ...

  9. 大厂面试官最喜欢问的面试难点

    一 平常经常使用外键和外键和级联吗,可以说说你对它们的理解吗? 对于外键和级联,阿里巴巴开发手册这样说到: [强制]不得使用外键与级联,一切外键概念必须在应用层解决. 说明:以学生和成绩的关系为例,学 ...

最新文章

  1. JavaScript_下_Dom
  2. C语言从青铜到王者——数组详解总结【一维数组、二维数组、字符数组、数组实例】
  3. 【AI不惑境】计算机视觉中注意力机制原理及其模型发展和应用
  4. object-c 1
  5. 如何在eclipse中自定义一个jar包名称
  6. 机器学习-预测之时间序列分析预测法原理及实战
  7. linux下面使用cpdf合并pdf
  8. java监听数据库操作_第十六篇——JDBC操作数据库之监听器
  9. nacos 适配达梦、人大金仓数据库
  10. 搭建cacti监控平台
  11. Java实训项目10:GUI学生信息管理系统 - 实现步骤 - 创建数据访问接口实现类
  12. 又真香了!到底是怎样的软件测试面试文档,拿到这么多大厂offer
  13. c语言遥控器程序设计,基于51单片机的红外线遥控器解码程序设计
  14. Python常用第三方库大全, 值得收藏!
  15. pythonmsgbox怎么使用_弹出MsgBox后Python是否继续执行代码?
  16. 开源夏令营之项目汇报7
  17. VC++ 利用MFC的CWindowDC类实现画线功能 在桌面窗口中画线 绘制彩色线条 CPen nPenStyle nWidth crColor
  18. springboot+java农家乐系统-住宿-美食-活动vue
  19. python统计单词个数算法_python 统计单词个数和频次
  20. k线图 TradingVeiw --简介篇

热门文章

  1. 持续集成工具 Jetbrains TeamCity 简介
  2. python3 多维数组 NumPy ndarray 简介
  3. linux 文本搜索命令 grep egrep fgrep 区别
  4. google chrome 谷歌浏览器 快捷键说明
  5. git clone 失败解决方法 --depth 1
  6. linux 内核 调试工具介绍
  7. linux 内核头文件 linux kernel header
  8. Android--相对布局
  9. 端口复用及其实现分析[Google Patch]
  10. php 头部utf8,PHP去掉utf8格式文件中的bom头部_PHP教程