1 Star 0 Fork 2

Emotion404 / JavaBooks

forked from 帝八哥 / JavaBooks 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
谈谈String.md 4.83 KB
一键复制 编辑 原始数据 按行查看 历史
DreamCats 提交于 2020-07-28 20:16 . 谈谈集合

难道面试官想考String的什么?

String、StringBuffer和StringBuilder的区别

面试官:说一下你知道的String、StringBuffer和StringBuilder的区别

我:其实总结说一下就行,三点不同

  1. 可变性
  • 简单的来说:String 类中使用 final 关键字修饰字符数组来保存字符串,private final char value[],所以 String 对象是不可变的。

  • StringBuilderStringBuffer 都继承自 AbstractStringBuilder 类,在 AbstractStringBuilder 中也是使用字符数组保存字符串char[]value 但是没有用 final 关键字修饰,所以这两种对象都是可变的。

  1. 线程安全

- String 中的对象是不可变的,也就可以理解为常量,线程安全。

- AbstractStringBuilderStringBuilderStringBuffer 的公共父类,定义了一些字符串的基本操作,如 expandCapacityappendinsertindexOf 等公共方法。StringBuffer 对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。StringBuilder 并没有对方法进行加同步锁,所以是非线程安全的。

  1. 性能

- 每次对 String 类型进行改变的时候,都会生成一个新的 String 对象,然后将指针指向新的 String 对象。

- StringBuffer 每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象并改变对象引用。相同情况下使用 StringBuilder 相比使用 StringBuffer 仅能获得 10%~15% 左右的性能提升,但却要冒多线程不安全的风险。

总结:

  • 操作少量的数据: 适用String

  • 单线程操作字符串缓冲区下操作大量数据: 适用StringBuilder

  • 多线程操作字符串缓冲区下操作大量数据: 适用StringBuffer

final关键字

面试官:有木有想过为什么String的char前面加了final,有什么好处?

我:答这个问题,你要先说final是干啥的

final关键字主要用在三个地方:变量、方法、类。

  • 对于一个final变量,如果是基本数据类型的变量,则其数值一旦在初始化之后便不能更改;如果是引用类型的变量,则在对其初始化之后便不能再让其指向另一个对象

  • 当用final修饰一个类时,表明这个类不能被继承。final类中的所有成员方法都会被隐式地指定为final方法。

  • 使用final方法的原因有两个。第一个原因是把方法锁定,以防任何继承类修改它的含义;第二个原因是效率。在早期的Java实现版本中,会将final方法转为内嵌调用。但是如果方法过于庞大,可能看不到内嵌调用带来的任何性能提升(现在的Java版本已经不需要使用final方法进行这些优化了)。类中所有的private方法都隐式地指定为final。

final修饰有啥好处

  • final的关键字提高了性能,JVM和java应用会缓存final变量

  • final变量可以在多线程环境下保持线程安全

  • 使用final的关键字提高了性能,JVM会对方法变量类进行优化;

了解String.intern()方法吗?

面试官:说一下String.intern()干嘛用的?

我:去字符串常量池拿吃的

  • jdk6:

执行intern()方法时,若常量池中不存在等值的字符串,JVM就会在常量池中创建一个等值的字符串(这句话很重要),然后返回该字符串的引用

  • jdk7:

执行intern操作时,如果常量池已经存在该字符串,则直接返回字符串引用,否则复制该堆中字符串对象的引用到常量池(堆对象引用复制到常量池)中并返回

简单说一下常量池版本的变化

1.6

  • 静态常量池在Class文件中。
  • 运行时常量池(常量池:字面量和符号引用)在Perm Gen区(也就是方法区)中
  • 字符串常量池在运行时常量池中。

1.7

  • 静态常量池在Class文件中。
  • 运行时常量池依然在Perm Gen区(也就是方法区)中。在JDK7版本中,永久代的转移工作就已经开始了,将譬如符号引用转移到了native heap;字面量转移到了java heap;类的静态变量转移到了java heap。但是运行时常量池依然还存在,只是很多内容被转移,其只存着这些被转移的引用。
  • 字符串常量池被分配到了Java堆的主要部分。也就是字符串常量池从运行时常量池分离出来了

1.8

  • 静态常量池在Class文件中。
  • JVM已经将运行时常量池从方法区中移了出来,在Java 堆(Heap)中开辟了一块区域存放运行时常量池同时永久代被移除,以元空间代替。元空间并不在虚拟机中,而是使用本地内存。因此,默认情况下,元空间的大小仅受本地内存限制。其主要用于存放一些元数据(类信息)。
  • 字符串常量池存在于Java堆中
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/Emotion404/JavaBooks.git
git@gitee.com:Emotion404/JavaBooks.git
Emotion404
JavaBooks
JavaBooks
master

搜索帮助

344bd9b3 5694891 D2dac590 5694891