相信在面试过程中很多面试官都会问到String,StringBuffer,StringBuilder的区别。但是对于它的机制,原理会头晕。这就要拿出JVM的工作原理了。
大家都知道String是由“字符”组成的串,在程序中使用的频率很高,String是java中的一个类,但又是一个特殊的类。具体特殊在哪?
1、 String类对象的创建方式有2种:
方式一:String str = new String("hello world"); //利用构造器创建。这是java类中很普遍的
方式二:String str = "hello world"; //这个类似于基本类型赋值,但是它又不是基本类型。
2、java class文件结构和常量池
Java程序要运行,首先需要编译器把源文件编译成字节码文件(即.class文件),然后由JVM来解释执行。
class文件是8bit的二进制流。文件中最开始的4个字节组成的叫magic(魔数),其作用在于分辨是否为class文件。紧接着是version,contant pool(常量池),Access rights ,Implemented interfaces,fields等等。
package com.wireless.xuwei; public class StringDemo { /** * @param args */ public static void main(String[] args) { System.out.println("hello world!"); } }
此时上述代码中的"hello world!"字符串字面值被编译之后,可以清楚的看到存放在了class常量池中的字符串常量表中。如图所示:
3、 JVM运行class文件的原理
源码被编译成class文件之后,JVM就要运行这个class文件。它首先会先用类装载器ClassLoader来加载class文件。(我们在开发过程中导入的jar包通常都是把class打成jar包,如果该包中的class的方法@hide,需要用到反射机制,此时也是通过类加载器加载这个class文件作为Class类的一个实例,再通过这个实例去获取它的属性,构造器,类方法或者是成员方法等)。当JVM把class文件加载完成后,会创建许多内存数据结构来存放class文件中的字节数据。如class文件中的属性,常量,类方法,方法中的二进制指令序列等信息。当然在运行的时候,需要为方法创建栈帧等。这些数据都会被JVM放到“方法区”,“堆”,“栈”。
4、拘留字符串对象
在java源码中的每一个字面值字符串(如String str = "java"),其中"java"就是字面值字符串,它会在编译成class文件时,形成标志号为8(CONSTANT_String_info)的常量表。当JVM加载class 文件时,会为对应的常量池建立一个内存数据结构,并存放在方法区中。同时JVM又会为字符串字面值"java"在堆中创建一个新的String对象,该对象叫拘留字符串对象。同时然后把常量表中的入口地址转为堆中挽留字符串对象的地址。
package com.wireless.xuwei; public class StringDemo { /** * @param args */ public static void main(String[] args) { System.out.println("hello world!"); String s1 = "a"; //s1指向的是拘留对象地址 String s2 = "a"; System.out.println(s1 == s2); //true 由此可见,源码中所有相同字面值的字符串 //都只能建立一个唯一的拘留字符串对象。 String str = new String("a");//在堆中分配一个String类对象的空间。 //str指向的是该对象的地址 String str2 = new String("a"); System.out.println(str == str2);//false 因为二者都是指对String类对象的地址值。但地址值不一样 String s3 = s1 + s2; String aa = "aa"; System.out.println(aa == s3);//false 因为s1是指向拘留对象的址,在进行"+" //运行时,JVM会在堆中创建一个StringBuilder的类,内容为挽留对象的内容。然后再 //调用append()把s2指向的挽留对象值追加进来,然后StringBuilder会调用toString() //会在堆中创建一个String类的对象,并将该String类的对象地址值给了s3 System.out.println(aa == "a" + "a");//true 因为在java中字面值的运行都是在编译期间就执行了。 //即aa指向的是一个拘留对象引用值,内容为"aa",而"a"+"a"在编译期间就成为了"aa" //此时JVM发现堆中已经存在内容一样的挽留对象,则不再创建新的对象,即二者即为同一个。 } }
5、 StringBuffer StringBuilder
StringBuffer它是一个线程安全的,可调用内部的一些方法(如appen())来达到改变字符串。
StringBuilder是一个非线程安全的。但是它的性能要超过StringBuffer,二者的使用几乎一样。
6、 总结
一) 在编译阶段就能确定的,即只有字面量字符串进行“+”时,选用String性能最好;如果字符串是从其他来 的,如String str = "a"; String str2 = str + "bc";它实质上就执行上述的JVM的顺序了。即先创建一个 StringBuilder类的对象。内容为拘留对象的内容"a",再执行append(),把另外一个挽留对象的内 容“bc”也加进来,再调用toString()方法再在堆中创建一个新的String类的对象。
二) 如果在进行“+”运算时,字符串内容是来自其他的String,"+"操作过多时会造成内存溢出的。因为 每”+“一次就创建一个新的对象,过多了JVM会来不及回收而造成内存溢出。
三)在没有线程安全要求的情况下,应选择StringBuilder,性能远强于StringBuffer
相关推荐
"String StringBuffer和StringBuilder区别之源码解析" 在Java中,字符串是我们经常使用的数据类型,而String、StringBuffer和StringBuilder是Java中三种常用的字符串类。在这篇文章中,我们将从源码角度对String、...
StringBuffer:字符创变量 StringBuilder:字符创变量 从上面的名字可以看到,String是“字符创常量”,也就是不可改变的对象。对于这句话的理解你可能会产生这样一个疑问 ,比如这段代码:
在Java编程语言中,String、StringBuffer和StringBuilder都是用来处理字符串的类,但它们之间存在显著的性能和功能差异。下面我们将深入探讨这三个类的区别。 首先,`String`类是Java中最基本的字符串类型,它表示...
在Java编程语言中,String、StringBuilder和StringBuffer都是用来处理字符串的类,它们之间存在一些重要的区别,主要涉及到性能和线程安全性。 首先,`String`类代表的是字符串常量,一旦创建,其内容就不能改变。...
在Java编程语言中,`String`、`StringBuffer`和`StringBuilder`是处理字符串的三个重要类,它们各自有特定的使用场景和优缺点。理解它们的差异对于编写高效的代码至关重要。 **String类** `String`是不可变的类,...
String, StringBuffer 与 StringBuilder 的区别 在 Java 中,String, StringBuffer 和 StringBuilder 三个类都是用于字符操作的,但它们之间有着很大的区别。 首先,String 是不可变类,意味着一旦创建了 String ...
stringbuilder用法 String、StringBuilder、StringBuffer 用法比较String、StringBuilder、StringBuffer 用法比较String、StringBuilder、StringBuffer 用法比较String、StringBuilder、StringBuffer 用法比较String...
String、StringBuffer 和 StringBuilder 是 Java 语言中三种不同类型的字符串处理方式,它们之间存在着明显的性能和线程安全性差异。 String String 类型是不可变的对象,每次对 String 对象进行改变时都会生成一...
在Java编程语言中,`String`、`StringBuffer`和`StringBuilder`都是用来处理字符串的类,但它们之间存在显著的差异,主要体现在性能、线程安全性和使用场景上。 首先,`String`是最基本的字符串类,它代表的是不可...
Java中的字符串处理是编程中常见的任务,涉及到三个关键类:String、StringBuffer和StringBuilder。它们在功能上相似,但有着重要的区别,主要体现在字符串的可变性、线程安全性和性能方面。 1. 可变性 - String类...
"Java 中 String、StringBuffer 和 StringBuilder 的区别及用法" Java 中 String、StringBuffer 和 StringBuilder 是三个常用的字符串操作类,了解它们之间的区别对 Java 开发者来说非常重要。本文将详细介绍这三者...
Java 中 String 和 StringBuffer 与 StringBuilder 的区别及使用方法 Java 中 String、StringBuffer 和 StringBuilder 是三个常用的字符串操作类,每个类都有其特点和使用场景。在开发过程中,正确选择合适的字符串...
string,stringbuffer,stringbuilder
string,stringBuffer,stringBuilder
Java 中 String, StringBuffer 与 StringBuilder 的区别 Java 中 String, StringBuffer 与 StringBuilder 三种字符串类型的区别是很多开发者经常混淆或不了解的知识点。今天,我们将深入探讨这三种字符串类型的区别...
String、StringBuilder、StringBuffer的区别 在 Java 中,String、StringBuilder 和 StringBuffer 三者都是字符串处理类,但是它们之间存在着本质的区别。本文将从执行速度、线程安全性、字符串处理方式等方面对这...
在Java编程语言中,String、StringBuffer和StringBuilder都是用来处理字符串的重要类,它们各自具有不同的特性和使用场景。下面将详细解析这三个类的区别。 首先,`String`类是最基础的字符串处理类,它被设计为不...
在Java编程语言中,String、StringBuffer和StringBuilder都是用来处理字符串的重要类,它们各自有特定的使用场景和特性。理解这三个类的区别对于任何Java开发者,无论是初学者还是经验丰富的程序员,都是非常重要的...
String,StringBuilder,StringBuffer