String字符串
java.lang.String
1、字符串的特点
1、字符串String类型本身是final声明的,意味着我们不能继承String。final类不能被继承。
2、字符串的对象也是不可变对象,意味着一旦进行修改,就会产生新对象
字符串的对象也是不可变对象
我们修改了字符串后,如果想要获得新的内容,必须重新接受。
如果程序中涉及到大量的字符串的修改操作,那么此时的时空(时间、空间 )消耗比较高。可能需要考虑使用StringBuilder或StringBuffer。
3、String对象内部是用字符数组进行保存的
String对象底层的存储
JDK1.9之前有一个char[] value数组,JDK1.9之后byte[]数组
JDK8 private final char value[];
JDK11 private final byte[] value;
4、String类中这个char[] values数组也是final修饰的,意味着这个数组不可变,然后它是private修饰,外部不能直接操作它,String类型提供的所有的方法都是用新对象来表示修改后内容的,所以保证了String对象的不可变。
5、就因为字符串对象设计为不可变,String对象不可变的特性,使得我们可以把一些字符串存到常量池中,字符串有常量池来保存很多常量对象
常量池在方法区。字符串有常量池。常量池中的是可以共享的。
字符串常量池在哪里?Oracle官方虚拟机HotSpot
如果细致的划分:
(1)JDK1.6及其之前:方法区
(2)JDK1.7:堆 挪到堆中,即在堆中单独划分了一块来存字符串常量
(3)JDK1.8:元空间 从堆中挪出,挪到一个“元空间meta space”,即类似于方法区。
String对象怎么就不可变?
①底层char[]数组有final修饰,意味着这个数组不能扩容等,来达到存更多的字符。
②char[]数组是私有的,我们程序员无法直接操作这个char[]数组,而且String没有提供这样的方法,来修改char[]数组的元素的值。
String提供的所有的方法,对字符串的修改都是给你返回一个新的字符串对象。
保证了String对象的不可变。
public class TestString01 {
@Test
public void test02(){
String s1 = "hello";
String s2 = "hello";
System.out.println(s1 == s2);//true
String s3 = new String("hello");
String s4 = new String("hello");
System.out.println(s3 == s4 );//false
}
@Test
public void test01(){
String s1 = "hello";
System.out.println(s1);//hello
s1 = "world";
System.out.println(s1);//world
s1 = s1 + "java";
System.out.println(s1);//worldjava
String s = "";
System.out.println(s);//
change(s);
System.out.println(s);//
}
public void change(String str){
str = "hello";
}
}
简单的String面试题
面试题:
Q1:String是最基本的数据类型吗?
A:
不是,Java基本数据类型只有8种,byte、short、int、long、float、double、char、boolean。
String(确实最常用)
Q2:"String、StringBuilder、StringBuffer的区别是什么?"
A2:
1、可变性。String不可变,StringBuilder与StringBuffer是可变的。
- String类中使用只读字符数组保存字符串,private final char value[],所以是不可变的(Java 9 中底层把 char 数组换成了 byte 数组,占用更少的空间)。
- StringBuilder与StringBuffer都继承自AbstractStringBuilder类,在AbstractStringBuilder中也是使用字符数组保存字符串,char[]value,这两种对象都是可变的。
可变性 String不可变 StringBuilder与StringBuffer是可变的
2、线程安全性。String和StrinbBuffer是线程安全的,StringBuilder是非线程安全的。
- String线程安全是因为其对象是不可变的,StringBuffer线程安全是因为对方法加了同步锁或者对调用的方法加了同步锁。
- StringBuilder并没有对方法进行加同步锁,所以是非线程安全的。
线程安全性 String和StringBuffer是线程安全的 StringBuilder是非线程安全的
3、性能。
- String的性能较差,因为每次对String 类型进行改变的时候,都会生成一个新的String对象,然后将指针指向新的String 对象。
- 而StringBuffer/StringBuilder性能更高,是因为每次都是对对象本身进行操作,而不是生成新的对象并改变对象引用。一般情况下StringBuilder 相比StringBuffer 可获得10%~15% 左右的性能提升。
String StringBuilder StringBuffer
- 如果要操作少量的数据用String;
- 单线程操作字符串缓冲区下操作大量数据StringBuilder;
- 多线程操作字符串缓冲区下操作大量数据StringBuffer;
参考资料
记录 - 搞定Java核心技术
高薪之路–Java面试题精选集
从Hello到goodbye