目录
1.创建字符串
Java中,字符串类型就是我们用双引号引起来的连续字符,如:"abcdef",而'a'这种的只是字符,String只是字符串的类型。
常见的构造String的方式
// 方式一
String str = "Hello Bit";
// 方式二
String str2 = new String("Hello Bit");
// 方式三
char[] array = {'a', 'b', 'c'};
String str3 = new String(array)
接下来我们再看这个代码
public static void func(String s,char[] array){
s = "hang";
array[0] = 'p';
}
public static void main(String[] args) {
String str = "abcdef";
char[] chars = {'c','u','t','e'};
func(str,chars);
System.out.println(str);
System.out.println(Arrays.toString(chars));
}
//打印结果
abcdef
pute
首先str和chars里面存储的都是abcdef和cute的地址,s里面存储的也是abcdef的地址,后面里面的地址改为hang的地址,因此只是改变了引用s所指向的对象,并没有改变内容,而后面的array[0]是改变了其所知的内容,将cute改为pute. 首先str和chars里面存储的都是abcdef和cute的地址,s里面存储的也是abcdef的地址,后面里面的地址改为挂起的地址,因此只是改变了引用所指向的对象,并没有改变内容,而后面的数组[0]是改变了其所知的内容,将位改为pute。
2.字符串相等的问题
运行时常量池:当程序把编译好的字节码文件加载到JVM中,会生成一个运行时常量池(存储在方法区)实际上是class文件常量池。
字符串常量池:主要存放字符串常量,本质上是一个哈希表,StringTable.在JDK1.8开始,放在了堆里面
public static void main4(String[] args) {
String str1 = "hello";
String str2 = new String("hello");
String str3 = "hello";
System.out.println(str1==str2);
}
在调试中也可以看出两个hello的地址相同,因此这其中str1先入常量池,随后str2直接引用常量池中的hello,因此两者相等。并且str2并不会入池。
public static void main6(String[] args) {
String str1 = "11";
String str2 = new String("1")+new String("1");
System.out.println(str1==str2);
}
这里我们先让str1=11先入池,再让1入池,再用1和1相互拼接,形成一个StringBuilder类型的对象。因为str2是String类型的,因此调用toString方法,将StringBuilder变为String类型。结果为false。
对于直接赋值的字符串常量(例如:String s = “Hello World”;中的 “Hello World”)也是放在栈区,而new出来的字符串对象是存放在堆内存中。所以需要手动入池。
String str2 = new String("1")+new String("1");
str2.intern();//手动入池,字符串常量池没有的时候,就会入池,有则不会入池
String str1 = "11";
System.out.println(str1 == str2);
此时结果则为true。
public class TestDemo2 {
public static void main7(String[] args) {
String str1 = null;//代表str1这个引用不指向任何对象
String str3 = "";//代表str3这个引用指向的字符串是空的
String str2 = "11";
//String底层是个value数组,此时11不能被改变,如果想改变,只能用反射
//调用方法之前一定是个引用或者类名,因此一定要防止其为空
System.out.println(str1.equals(str2));
}
如果我们想比较字符串的内容时,则使用equals方法,但在使用之前我们应该先判断str1是否为空