文中部分内容来自尚硅谷康师傅处,共同学习
文章目录
一、String的基本特性
1、String:字符串,最常见的两种创建方式
(1) 方式一:String str1 = “qingdianguanzhu”。// 字面量定义的方式,数据存储于字符串常量池中
另外说一下什么是字面量,通俗来讲就是:直接定义的字符串,用双引号引起来的字符串,会在字符串常量池中唯一存在的字符串都是字面量。
(2)方式二:String str2 = new String (“hello”)
2、String 底层用 final
修饰,也就意味着 String 类是不可以被继承,而且一旦定义就不可变
3、String 实现了 Serializable
接口:表示字符串是支持序列化的,可以跨进程来传输数据;
还实现了 Comparable
接口:表示 String 可以比较大小,比如电话簿会按照首字母来排序
4、String 在jdk8 及以前内部定义了 final char value[]
用于存储字符串数据。jdk9 时改为 final byte value[]
动机是什么:我们都知道 char类型是占两个字节,而在堆当中大部分存储的还是字母这样的拉丁文,一个byte就可以存储,要是用char的话就会浪费一个字节的空间,所以在jdk9 就改为使用 byte[],那么像中文这样的使用GBK都要两个字节的数据怎么用一个字节的byte存储得下呢,是这样的,它会做一个编码标识,就是像中文这样不止一个字节的,就采用byte加上编码标记的方式去存储多个字节。
另外:StringBuffer
和 StringBuilder
也是同样做了一定的修改。
5、String 的不可变性
一个字符串一旦被创建其空间内的值打死也不会被修改。只会再去创建一个新的字符串空间,而不会直接修改原来的字符串,也就是说字符串一旦被创建就不可以去修改它的值(包括添加数据、删除一个多几个数据)
例子1
// String 的不可变性
String s1 = "abc";
String s2 = s1.replace('a','m');
System.out.println(s1); // abc
System.out.println(s2); // mbc
s2 += "def";
System.out.println(s2); // mbcdef
例子2
6、字符串常量池中是不会存储相同内容的字符串的
原理:String 的 String pool 是一个基于Map 实现的Hashtable,首先Map 存储形式的是key-value键值对的,由于key 的值是不重复的,那么就用于存储String 字符串,那么这么Map 的value 值是什么呢,它是用一个final 修饰的常量区表示的,取值时只取key 就好了。
那么这个String pool 到底有多大呢 ?
在jdk 6 中StringTable 时固定的,就是1009的长度,所以如果常量池中的字符串过多就会导致效率下降很快,原因是Hash 冲突更加的严重了。
在jdk 7 中,StringTable 的长度默认值是60013,可以通过-XX:StringTableSize 去设置StringTable 的长度,其值可以在 1009 ~ 以2开头的一个23位数字。当然也不用设置过大,这样就会占用很多 堆空间。
二、String 的内存分配
1、常量池相当于一个Java系统级别提供的缓存。String 类型的常量池比较特殊,它的主要使用方法有两种:
(1) 直接使用双引号声明出来的 String 对象会直接存储在常量池中。如: string str = “woani” ;
(2) 如果不是用双引号声明的 String 对象,可以使用