提示:以下是本篇文章正文内容,Java系列学习将会持续更新
一、初步认识
- String不是基本数据类型;而是Java中的一种包装类,重写了
equals()
方法。 - String类不可被继承,String对象是可不变的,因为被 final 修饰。
- String实例的字符串都是同过 char[] 储存的。
- String 类中每一个看起来会修改 String 值的方法,实际上都是创建了一个全新的 String对象,以包含修改后的字符串内容。而最初的 String 对象则丝毫未动 。
回到目录…
二、创建字符串的三种方式
- 直接赋值:只会开辟一块堆内存空间,并且该字符串对象可以自动保存在对象池中以供下次使用。
String str = "Welcome to java";
//推荐这种方式,只产生一个对象,节省空间
- 构造方法:会开辟两块堆内存空间,不会自动保存在对象池中。
String str = new String("Welcome to java");
//会产生两个对象,产生垃圾空间
这种方式的缺点:
a. 如果使用String构造方法就会开辟两块堆内存空间,并且其中一块堆内存将成为垃圾空间(字符串常量 “hello” 也是一个匿名对象, 用了一次之后就不再使用了, 就成为垃圾空间, 会被 JVM 自动回收掉).
b. 字符串共享问题. 同一个字符串可能会被存储多次, 比较浪费空间.
// 可以手工入池,intern();不会创建垃圾空间
String str1 = new String("hello").intern();
String str2 = "hello";
System.out.println(str1 == str2); //输出:true
- 通过char[]数组创建字符串
char[] data = {'h','e','l','l','o'};
String str = new String(data);
三、字符串常量池
String类的设计使用了共享设计模式。
在JVM底层实际上会自动维护一个字符串常量池:
- 如果现在采用了直接赋值的模式进行String类的对象实例化操作,那么该实例化对象(字符串内容)将自动保存到这个对象池之中。
- 如果下次继续使用直接赋值的模式声明String类对象,此时对象池之中如若有指定内容,将直接进行引用。如若没有,则开辟新的字符串对象而后将其保存在对象池之中以供下次使用。
四、理解字符串的不可变性
String str = "hello";
str = "world";
System.out.println(str); //输出:world
五、通过反射破坏String类
通过反射强行破坏String类的封装,获取value数组进行改变。
听听就行了:
import java.lang.reflect.Field;
public class Test {
public static void main(String[] args) throws Exception{
String str = "hello";
//通过反射获取String类中的value数组
Field field = String.class.getDeclaredField("value");
//value的private定义取消掉
field.setAccessible(true);
//获取到str对象内部的value数组
char[] value = (char[]) field.get(str);
value[0] = 'H';
System.out.println(str); //输出:Hello
}
}
六、与StringBuilder的关系
为了方便字符串的修改,引入这两个类,它俩大部分功能是相同的。
StringBuffer : 线程安全
StringBuilder : 线程不安全,但是更快
实际上它们与String类没有一点关系,没有血缘关系。
当出现字符串拼接 “+” 时,JVM会自动把字符串转换成StringBuilder类型的,调用其中的append()
方法扩展字符串,避免产生过多的垃圾空间。
七、equals 和 == 的判断
equals()方法是判断两个对象的内容是否相同,而 == 是判断是否为同一个对象。
String str1 = new String("hello");
String str2 = new String("hello");
System.out.println(str1.equals(str2)); // true
System.out.println(str1 == str2); // false
String str3 = "world";
String str4 = new String("world");
System.out.println(str3.equals(str4)); // true
System.out.println(str3 == str4); // false
String str5 = "张三";
String str6 = "张三";
System.out.println(str5.equals(str6)); // true
System.out.println(str5 == str6); // true
总结:
提示:这里对文章进行总结:
以上就是今天的学习内容,本文是JavaSE的学习,深度剖析String类,学习字符串创建的方式,字符串的不可变性,以及字符串常量池。之后的学习内容将持续更新!!!