字符串的简单理解,就是由多个字符组成的一串数据叫字符串, 也可以看作一个字符数组
Java中所有的字符串文字(例如"abc")都被实现为此类的实例(对象)。
1、字符串字面值"abc"也可以被成为一个字符串对象
2、字符串是常量,一旦被赋值,就不能被改变
构造方法:
public String()
public String(byte[] bytes)
public String(byte[] bytes,int offset,int length)
public String(char[] value)
public String(char[] value,int offset,int count)
public String(String original)
字符串的方法:
public int length()返回此字符串的长度。
例子
package test.StringDemo;
public class demo1 {
public static void main(String[] args) {
//构造方法public String()
String s = new String();
System.out.println("s: "+s);
System.out.println("字符串s长度为 "+s.length());
String ss = new String("abc");
System.out.println("ss: "+ss);
System.out.println("字符串ss长度为 "+ss.length());
System.out.println("=============");
//构造方法 public String(byte[] bytes) 将一个字节数组转为一个字符串
byte[] b = {97,98,99,100,101};
String s1 = new String(b);
System.out.println("s1: "+s1);
//构造方法 public String(byte[] bytes,int index,int length)
//将字节数组中的一部分截取出来变成一个字符串
String s2 = new String(b,1,3);
System.out.println("s2 "+s2);
System.out.println("=============");
//构造方法 public String(char[] value)
//将一个字符数组转化成一个字符串
char[] c = {'a','b','c','字','符','串'};
String s3 = new String(c);
System.out.println("s3: "+s3);
//构造方法 public String(char[] value,int index,int count)
//将字符数组中的一部分截取出来变成一个字符串
String s4 = new String(c,1,4);
System.out.println("s4: "+s4);
System.out.println("=============");
//public String(String original)
String s5 = "original";
String s6 = new String(s5);
System.out.println("s6: "+s6);
}
}
先来看一段代码
public class demo2 {
public static void main(String[] args) {
String s = "hello";
s = s+"world";
System.out.println(s);
}
}
结果为helloworld,这里s对应的值从hello变成了helloworld,那么为什么还说字符串一旦被赋值就不能被改变呢?
当我们使用String s = “hello”;语句创建字符串的时候,首先会去常量池中查找,如果有,就返回这个常量的地址,如果没有,在常量池中创建并返回。
比如这里的“hello”,一开始是没有的,所以要先创建,然后返回一个地址,比如0x001
下一次,如果String ss = “hello”;的时候,ss指向的也会是这个0x001的地址
String s = "hello"; //常量池中没有常量"hello"就创建,假设地址值为0x001
String s1 = "hello"; //在常量池中查找到"hello",因此s1也指向地址0x001
System.out.println(s==s1); //地址值相同,所以返回的结果为true
之后 s = s+“world”; 语句中出现了“world”,同样要在常量池中创建
现在需要将“hello”与“world”进行拼接,这里的拼接会开辟出一个新的地址空间,然后将拼接后的”helloworld“放入
之前的变量s会重新指向这个新的地址0x003,而不是原先的0x001
所以说字符串一旦被创建,值就不可改变
这里的值指的字符串本身的值,而不是地址值
那么现在需要思考下一个问题
package test.StringDemo;
public class demo2 {
public static void main(String[] args) {
String s1 = new String("hello");
String s2 = "hello";
System.out.println(s1 == s2); // false
System.out.println(s1.equals(s2)); //true
}
}
这里可以发现s1与s2的内容相同,但是地址不同
这里需要确认三件事情
知道了这三点,再来看具体的操作过程
首先是String s1 = new String(“hello”);
new String()会在堆内存中创建对象,而引用变量String s1则会在栈里面被创建,然后s1指向堆内存中被创建的String对象
”hello“也会在常量池中被创建,然后new String()创建的String对象会指向”hello“的地址,比如0x001,而String对象本身在堆内存中的地址,假设为0x0001,两个地址是不一样的
因此,这里的引用变量s1指向的是堆内存中String对象地址0x0001,而不是直接指向常量池中”hello“的地址0x001
String s2 = “hello”;中的引用变量s2在栈里面被创建后,就可以直接指向常量池中”hello“的地址0x001
package test.StringDemo;
public class demo4 {
public static void main(String[] args) {
String s1 = "hello";
String s2 = "world";
String s3 = "helloworld";
System.out.println(s3==(s1+s2)); //false
System.out.println(s3==("hello"+"world")); //true
}
}
s3==(s1+s2)的结果是false,是因为变量相加是先在常量池中开辟空间,然后将拼接后的字符串放入开辟的空间之中,因此地址会改变。
s3==(“hello”+“world”)的结果是true,是因为常量相加,是先拼接,然后在常量池中查找,是否有拼接后的字符串,如果有就返回这个地址值,如果没有才会创建新的空间。因为之前s3已经创建了”helloworld“字符串,所以返回的是s3指向的这个地址。因此地址相同。
那么还有一个问题,这里我们通过s1+s2的方式在常量池中创建了一个字符串”helloworld“,假设这个地址是0x001。那么原先s3指向的字符串同样是”helloworld“,假设地址是0x002。
这里的内容相同,但是地址不同,如果此时我再创建一个呢?比如
package test.StringDemo;
public class demo4 {
public static void main(String[] args) {
String s1 = "hello";
String s2 = "world";
String s3 = "helloworld";
String s4 = s1+s2;
String s5 = "helloworld";
}
}
s5会在常量池中查找"helloworld",如果找到就返回地址,可是这里不仅找到了,而且一下子找到了两个,那么会返回哪个地址呢?
package test.StringDemo;
public class demo4 {
public static void main(String[] args) {
String s1 = "hello";
String s2 = "world";
String s3 = "helloworld";
String s4 = s1+s2;
String s5 = "helloworld";
System.out.println(System.identityHashCode(s3)); //第一行
System.out.println(System.identityHashCode(s4)); //第二行
System.out.println(System.identityHashCode(s5)); //第三行
}
}
第一行与第三行返回的值相同,说明s5优先指向的地址是s3一开始就创建的地址