String的创建
关于String的创建方式有多种
我们来列举我们常见的方法来示例
package Class;
public class StringTest {
public static void main(String[] args) {
//1、直接创建一个字符串对象存在字符串常量池(其实也是存放在堆中)
//不过在之后的比较字符串就能够看到不同
String a = "sa ";
//2、新建一个字符串对象存在堆中
String b = new String("aaaa");
char[] c = new char[]{'a', 'c', 'd'};
String d = new String(c);
System.out.println(a);
System.out.println(b);
System.out.println(d);
}
}
这是输出结果
引用类型 – String类
在介绍String类是如何使用内存之前,我们现要明确一个信息,那就是String类是一个引用类型,Java中的数组、String类以及自定义的类都是引用类型。
关于引用的介绍,我们可以大致认为引用是一个缩减版的指针,但是我们平常用的时候并不会看到地址,因为编译器会帮助我们自动解析(也就是解引用)。
那为什么说引用是一个缩减版的指针呢?指针具有的数字运算在引用中是不存在的,因此我们说引用是缩减版的指针。
通过下面的图我们可以看出来引用其实就是一个变量,创建的字符串对象放在堆中,我们创建的引用就是用来存放字符串在堆中的地址的变量。
字符串比较相等
我们使用.equals来进行字符串的比较,使用==时比较的是字符串的地址
先来看一组实例
package Class;
public class StringTest {
public static void main(String[] args) {
String a = "aa";
String b = new String("aa");
System.out.println( a == b );
System.out.println(a.equals(b));
}
}
以上的代码运行就是这样的
再看看下方
package Class;
public class StringTest {
public static void main(String[] args) {
String a = "aa";
String b = "aa";
System.out.println( a == b );
System.out.println(a.equals(b));
}
}
以上代码运行结果
那么为什么会出现以上的问题呢?
直接赋值与构造方法赋值
先了解字符串的赋值方式
首先是直接赋值,之后是构造方法来赋值
第一个字符串对象采用的是直接赋值,第二个采用的是使用构造方法来进行赋值。
首先是因为String类设计采用了共享设计模式,JVM会自动维护一个字符串常量池
如果采用直接赋值的方法的话,若字符串常量池没有与该字符串相同的内容,那么会在字符串常量池中给这个字符串常量划分一块内存,用来存储。
如果采用直接赋值的时候的字符串为字符串常量池中已经有的内容,那么会直接从这个内存中拷贝出一个字符串对象,地址是不变的。如图所示
而当采用构造方法来进行赋值的时候。会开辟两个堆空间来进行字符串的构造,其中一块一定会成为垃圾空间。
构造方法来创建: String str = new String("hello");
使用这种方法,会先new一个堆空间,之后hello也会占用一个堆空间,并且hello占用的这个空间会成为垃圾对象,不会被使用,被使用的只是new出来的。
当使用构造方法的时候,首先产生一个匿名对象"hello",之后new出来一个"hello”以前的"hello”所在的空间就成为垃圾空间
请解释String类中两种对象实例化的区别
- 直接赋值:只会开辟一块堆内存空间,并且该字符串对象可以自动保存在对象池(常量池)中以供下次使用。
- 构造方法:会开辟两块堆内存空间,不会自动保存在对象池中,可以使用intern()方法手工入池。
字符串不可变
String str = "hello" ;
str = str + " world" ;
str += "!!!" ;
System.out.println(str);
// 执行结果
hello world!!!
Java中的字符串是可以用加号来进行拼接的,那字符串本来是不可变的,为什么还能使用加号来进行拼接得到呢?
其实是在每一次拼接完成时,字符串就创建了一个新的对象,其对象的值就是字符串拼接后的值,所以每一次拼接并不是改变了字符串本身的值,而是改变了字符串的引用所指向的地址。
字符串常用方法
(注:本图转自菜鸟教程 链接:https://www.runoob.com/java/java-string.html)