(一)两种实例化方法
(二)字符串的相等比较
(三)String的匿名对象
(四)两种实例化的区别
(五)字符串不可改变
(一)两种实例化方法
- 直接赋值
即使用字符串常量直径二初始化一个String对象。
举例如下:
String str1 = "hello";//直接赋值
System.out.println(str1);
//此时应该输出 hello
- 构造法
即使用String的构造方法初始化字符串对象。
举例如下:
String str1 = new String("hello");//堆空间上开辟两个内存块
System.out.println(str1);
//此处输出hello
(二)字符串的相等比较
-
基本数据类型比较——使用 ==
-
引用数据类型比较——使用 equals 关键字
比如字符串str1 和 str2 比较,str1.equals(str2) -
== 是用来进行数值比较的;若使用 == 用来比较字符串,则比较的是字符串对象的内存地址比较;
-
equals 则是进行字符串对象的 内容比较。
举例如下:
(1)基本数据类型可以使用 == 比较
public class TestString11_20{
public static void main(String[] args){
int num1 = 3;
int num2 = 3;
System.out.println(num1 == num2);
//此时结果为 true
}
}
运行结果如下:
(2)引用数据类型不可以使用 == 比较
public class TestString11_20{
public static void main(String[] args){
String str1 = "hello"; //匿名对象
String str2 = new String("hello");
System.out.println(str1 == str2);
//虽然str1 与str2内容一样,但此处结果为false,说明str1 与 str2 不相等
//此时str1 与 str2 比较的是内存地址的值而并非内容
}
}
运行结果如下:
(3)字符串比较使用equals
public class TestString11_20{
public static void main(String[] args){
String str1 = "hello"; //匿名对象
String str2 = new String("hello");
System.out.println("str1 equals str2 :"+str1.equals(str2));
}
}
运行结果如下:
(三)String的匿名对象
String str1 = “hello”;
hello即匿名对象,此时只不过给匿名对象起了名字 str1.
注意:
如果要判断用户输入的字符串是否等同于特定字符串,一定要将特定字符串写 在前面。
(即比较时将匿名对象卸载前面。)
匿名对象.equals(用户输入的字符串对象)。
原因:防止用户输入的字符串为空。出现 NullPointerException 错误。
举例如下:
public class TestString11_20{
public static void main(String[] args){
String str1 = null;
String str2 = "hello";
System.out.println("str1 equals str2 :"+str1.equals(str2));
}
}
运行结果会报错:
应该严格将匿名对象卸载前面,这样就不会报错:
public class TestString11_20{
public static void main(String[] args){
String str1 = null;
String str2 = "hello";
System.out.println("str1 equals str2 :"+str2.equals(str1));
}
}
运行结果如下:
(四)实例化的区别
String类的设计使用了共享设计模式
在JVM底层实际上会自动维护一个对象池(字符串对象池),如果现在采用了直接赋值的模式进行String类的对象 实例化操作,那么该实例化对象(字符串内容)将自动保存到这个对象池之中。如果下次继续使用直接赋值的模式 声明String类对象,此时对象池之中如若有指定内容,将直接进行引用;如若没有,则开辟新的字符串对象而后将 其保存在对象池之中以供下次使用
- 使用直接赋值法赋值的时候,使用的是共享池,如在堆内存中有一块内存为 hello,若 str1,str2,,,等的对象内容都是hello,则它们指向同一块堆内存,所以使用 == 比较的时候,它们的内存地址的值都相等。
- 使用构造方法的时候,在堆内存中本身就存在一块内存,内容为hello,使用构造方法是将该内容拷贝一份,放在另外一块堆内存上。所以说使用构造方法的时候,是开辟了两个内存块。所以内存地址的值已经发生变化。
(1)直接赋值:只会开辟一块堆内存空间,并且该字符串对象可以自动保存在对象池中以供下次使用。
(2) 构造方法:会开辟两块堆内存空间,其中一块成为垃圾空间,不会自动保存在对象池中,可以使用 intern()方法手工入池。
(1)直接赋值法
public class TestString11_20{
public static void main(String[] args){
String str1 = "hello"; //堆空间上开辟一个内存块并且共存(字符串共享池)
String str2 = "hello";
String str3 = "hello";
System.out.println(str1 == str2);//true
System.out.println(str2 == str3);//true
System.out.println(str1 == str3);//true
}
}
运行结果如下:
(2)采用构造方法
public class TestString11_20{
public static void main(String[] args){
String str1 = "hello";
String str4 = new String("hello");//堆空间上开辟两个内存块
System.out.println(str1 == str4);//false
}
}
运行结果如下:
使用构造方法时,String提供方法入池操作:
public String intern() ;
public class TestString11_20{
public static void main(String[] args){
String str4 = new String("hello").intern();//入池操作
//String str4 = new String();
//str4 = str4.intern();
//该语句等价于上面的入池语句
String str1 = "hello";
System.out.println(str1 == str4);//false
}
}
运行结果如下:
(五)字符串不可改变
字符串一旦定义不可改变。
即字符串本身不发生改变,是字符串对象的引用一直在变化。
如果对字符串进行修改,会创建新的字符串对象。
不要在循环里进行 大量的字符串拼接。