java中的字符串类型(String、StringBuffer、StringBuilder)

一、首先来说一下JVM相关的一些知识

我们先来了解一下JVM内存中的栈(stack)、堆(heap)和方法区:

  •  栈中保存的是:基本数据类型的变量、对象的引用、函数调用的现场。

  •  堆中保存的是:通过new关键字和构造器创建的对象。堆是垃圾收集器管理的主要区域。

  •  它们之间的区别是:栈中的数据可以共享、栈空间操作起来最快但是栈很小,通常大量的对象都是放在堆空间,栈和堆的大小都可以通过JVM的启动参数来进行调整,栈空间用光了会引发StackOverflowError,而堆和常量池空间不足则会引发OutOfMemoryError。

  •  举例说明:String str = new String(“hello”)这个语句中变量str放在栈上,用new创建出来的字符串对象放在堆上,而”hello”这个字面量是放在方法区的。

String类型的值是存在于常量池中的

private final char value[];

从String类的源码可以看出String是用字符串数组来存储对象的,并且是final类型的,这就说明String类型的对象被声明后是不能改变的,每次改变String类型的对象后就会产生一个新的对象,然后将指针指向新的对象。(两种创建方式还有区别)所以当一个对象需要频繁的改变的时候不应该被声明称String类型的,因为此时会产生大量新的对象,导致JVM的GC,影响程序性能。

二、String

看两个例子

String s1=“java”;

String s2=new String(“java”);

这两种方式创建出的对象虽然都是不可变的,但是创建方式时不同的。

第一种直接赋值的创建方式JVM首先会检查字符串常量池中有没有”java”这个字符串对象存在,如果有就返回java对象的引用,否则就在字符串常量池中新建一个字符串对象,并将它的引用返回。当改变这个字符串的时候回重新检查字符串常量池中是否有新的字符串。

第二种创建方式不管字符串常量池中有没有相同内容的对象,JVM都会在堆中创建一个新的对象,并将对象的引用返回。过程是,当使用new创建String对象时首先从字符串常量池中取一个实例的引用,然后在堆中新建一个对象,如果常量池中没有相同内容的实例则只在堆中创建一个对象,当调用intern方法后才将对应的字符串序列化放入常量池中。

  • String对象的实例调用intern方法后,可以让JVM检查常量池,如果没有实例的value属性对应的字符串序列比如"123"(注意是检查字符串序列而不是检查实例本身),就将本实例放入常量池,如果有当前实例的value属性对应的字符串序列"123"在常量池中存在,则返回常量池中"123"对应的实例的引用而不是当前实例的引用,即使当前实例的value也是"123"。

三、StringBuffer和StringBuilder

StringBuffer线程安全

StringBuilder线程不安全,速度优于StringBuffer,通常用于单线程

(待续)

猜你喜欢

转载自blog.csdn.net/qq_37570296/article/details/83587024