1.String类的实例化方式
- 直接赋值
String str = "hello world"; //str是一个对象的引用,所以“hello world”应该保存在堆内存中
System.out.println(str);
- 传统方法(构造方法)
//因为String是一个类,所以存在构造方法
String str = new String("hello world"); //通过构造方法赋值
System.out.println(str);
2. String字符串比较
- 如果有两个int型变量,判断是否相等用
==
判断
int x = 10;
int y = 10;
System.out.println(x==y); //true
- 如果是两个String进行比较,使用“ == ” 比较,比较的是引用类型的地址
String str = "hello world";
String str1 = "hello world";
String str2 = new String("hello world");
System.out.println(str == str1); //true
System.out.println(str2 == str1); //false
- 用equals方法比较字符串的内容
String str1 = "hello world";
String str2 = new String("hello world");
System.out.println(str1.equals(str2)); //true
总结:
- “ == ”操作符用于比较两个变量的值是否相等,对于基本类型,比较的就是数值大小;对于引用数据类型,比较的是保存的Java中String类详细描述,而不会比较内容
- 在字符串内容比较时,用String类提供的equals() 方法,区分大小写;使用**equalsIngoreCase()**不区分大小写
- 当使用直接赋值时,将判断字符串是否存在对象池中,如果有,则直接引用去指向对象池
- 对象池相当于一个一维数组
- 如果使用的是构造方法,则新开辟一个空间
3. String的匿名对象(没起名字的对象)
所有的字符串常量 " "
,都是String类的匿名对象
String str1= "hello";
String str = new String("hello");
System.out.println(str1.equals(str));
System.out.println("hello".equals(str));
- "String str = " hello "; “本质上就是将一个匿名的String类对象设置有名字,而且保存在堆内存中
- 任何的字符串常量都是String的匿名对象,所以该对象永远不会为空
4. 实例化区别
- 采用直接赋值
String str = "hello";
String str2 = "hello";
Stirng str1 = "hello";
System.out.println(str == str1); //true
System.out.println(str == str2); //true
System.out.println(str1 == str2); //true
//str, str1 , str2三个地址指向同一块空间
JVM底层其实会自动维护一个字符串常量池(对象数组)。如果采用直接赋值实例化对象,先在对象池中寻找是否有指定内容对象,若有,则直接引用;反之,则新创建;其实使用的就是设计模式中的享元模式
- 采用构造方法
String str = new String("hello");
String str1 = "hello";
System.out.println(str == str1); //false
- 采用构造方法会开辟两块堆空间
- 先放的是匿名对象“hello” ,是字符串常量开辟的,然后new一个真正的对象;指向的是new出来的真正的对象,匿名对象那块内存会成为垃圾空间
- 实例化的对象并不会保存在内存池中
//入池操作
//把String对象入池(如果池中有,引用指向它;如果没有,入池加指向)
String str = "hello";
String str1 = new String("hello").intern();
System.out.println(str == str1); //true
5. 字符串不可变更
- 字符串一旦定义,不可改变
- 所有语言对字符串的实现,都是字符数组,数组的最大缺陷就是长度固定。在定义字符串常量时,它的内容不可变
String str = "hello";
str = str +" world";
str += "!!!";
System.out.println(str); //hello world!!!
//4块垃圾空间
//堆中常量的值无法修改,但是栈的指向一直发生变化
以上字符串的变更,是对字符串对象的变更,而非字符串常量
图示如下: