JAVA基础题-String、Stringbuilder、Stringbuffer的区别

1、对JAVA平台的理解

Java 本身是一种面向对象的语言,最显著的特性有两个方面,一是所谓的“书写一次,到处运行”(Write once, run anywhere),能够非常容易地获得跨平台能力;另外就是垃圾收集(GC, Garbage Collection),Java 通过垃圾收集器(Garbage Collector)回收分配内存,大部分情况下,程序员不需要自己操心内存的分配和回收。

我们日常会接触到 JRE(Java Runtime Environment)或者 JDK(Java Development Kit)。 JRE,也就是 Java 运行环境,包含了 JVM 和 Java 类库,以及一些模块等。而 JDK 可以看作是 JRE 的一个超集,提供了更多工具,比如编译器、各种诊断工具等。

对于“Java 是解释执行”这句话,这个说法不太准确。我们开发的 Java 的源代码,首先通过 Javac 编译成为字节码(bytecode),然后,在运行时,通过 Java 虚拟机(JVM)内嵌的解释器将字节码转换成为最终的机器码。但是常见的 JVM,比如我们大多数情况使用的 Oracle JDK 提供的 Hotspot JVM,都提供了 JIT(Just-In-Time)编译器,也就是通常所说的动态编译器,JIT 能够在运行时将热点代码编译成机器码,这种情况下部分热点代码就属于编译执行,而不是解释执行了。

总结:

  • Java源代码经过Javac编译成.class文件

  • .class文件经JVM解析或编译运行

    • 解析:.class经过JVM内嵌的解析器解析执行
    • 编译:存在JIT编译器把经常运行的代码作为"热点代码"编译与本地平台相关的机器码,并进行各种层次的优化
    • AOT编译器:JAVA9提供的,直接将字节码编译成机器代码

2、String、StringBuffer、StringBuilder区别

String是java的基础类,提供构造与管理字符串的基本逻辑,它被声明为final class,所有属性也是final的,所以String是一个不可变类,由于它的不可变性,类似裁剪、拼接字符串都会产生新的String对象。

StringBuffer就是为了解决String拼接产生太多中间对象的问题而提供的类,本质上是一个线程安全的可修改字符序列.

StringBuilder是jdk1.5新增的,在能力上与StringBuffer没有区别,去除了线程安全部分,绝大部分场景进行拼接字符串首选

拓展:

  • 字符串的设计与实现

    1. String因为是不可变的,所以原生保证了基础线程安全,由于不可变,Immutable 对象在拷贝时不需要额外复制数据。
    2. StringBuffer线程安全是通过把各种修改数据方法加上synchronized 关键字实现的。
    3. 为了实现修改字符序列的目的,StringBuffer 和 StringBuilder 底层都是利用可修改的(char,JDK 9 以后是 byte)数组,二者都继承了 AbstractStringBuilder,里面包含了基本操作,区别仅在于最终的方法是否加了 synchronized。
    4. StringBuilder 的内部数组大小构建时为初始字符串大小+16,扩容机制是新字符串超度加原有的长度*2+2;
    5. 在java8中非静态的字符串拼接会在编译后自动转为StringBuilder 实现,在java9中更加特别,Java 9 利用 InvokeDynamic,将字符串拼接的优化与 javac生 成的字节码解耦,假设未来 JVM 增强相关运行时实现,将不需要依赖 javac 的任何修改。
  • 字符串的缓存

    1. String在java6以后提供了intern()方法,目的是提示JVM缓存字符串,但是intern()并不推荐使用,因为被缓存的字符串是存在于PermGen(永久代)里的,空间也很有限,基本不会被FullGC之外的垃圾收集照顾到,如果使用不当,OOM就会到来。
    2. 后续版本中,缓存被放置在了堆中,这样就极大避免了永久代占满问题,在java8中,永久代已经被MetaSpace(元数据区)替代率,而且默认缓存大小从最初的1009到7u40版本后修改为60013
  • string的演化

    1. 在jdk9版本前,string使用的是char数组存数据的,这样非常直接,java中一个char是两个bytes大小,拉丁语系不太需要太宽的char,所以就造成一定的浪费
    2. 在java6中 oracle jdk 提供了压缩字符串的特性,但是这个特性并不是开源的,实践中也有一定问题,最新版本的jdk已经移除了
    3. 在java9中,引入了Compact Strings 的设计,对字符串进行了改进。将数据存储方式从 char 数组,改变为一个 byte 数组加上一个标识编码的所谓 coder,并且将相关字符串操作类都进行了修改。另外,所有相关的 Intrinsic 之类也都进行了重写,以保证没有任何性能损失。虽然底层实现发生了这么大的改变,但是 Java 字符串的行为并没有任何大的变化,所以这个特性对于绝大部分应用来说是透明的,绝大部分情况不需要修改已有代码。
    4. 当然,在极端情况下,字符串也出现了一些能力退化,比如最大字符串的大小。你可以思考下,原来 char 数组的实现,字符串的最大长度就是数组本身的长度限制,但是替换成 byte 数组,同样数组长度下,存储能力是退化了一倍的!还好这是存在于理论中的极限,还没有发现现实应用受此影响。
    5. 在通用的性能测试和产品实验中,我们能非常明显地看到紧凑字符串带来的优势,即更小的内存占用、更快的操作速度
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值