一、实例化 String 类对象
- 直接为
String
赋值
public class Test{
public static void main(String[] args) {
String name = "Java"; // 实例化 String 对象
System.out.println("name:" + name);
}
}
- 直接调用
String
类中的构造方法
// String 存在以下的构造方法
public String
// 直接调用 String 类中的构造方法
```java
public class Test{
public static void main(String[] args) {
String name = new String("Java"); // 实例化 String 对象
System.out.println("name:" + name);
}
}
- 8
- 9
- 10
- 11
- 12
二、String 对象的内容比较
- 使用
==
比较字符串的内容
== :是用地址值进行比较的
- 1
public class Test{
public static void main(String[] args) {
String str1 = "hello";
String str2 = new String("hello");
String str3 = str2;
System.out.println("str1 == str2 -->" + (str1==str2));
System.out.println("str2 == str3 -->" + (str2==str3));
}
}
- 8
- 9
由结果可知,虽然程序中 String 的内容都是一样的,但是比较结果却不一致。
从图中我们可知,每个 String 对象的内容实际上都是保存在堆内存之中的,而且堆中的内容也是相同的。但是对 str1 和 str2 来说,内容分别保存在不同的空间,所以即使内容相同,地址的值也是不同的
因为 ==
是用地址值进行比较的。
- 使用
equals()
方法对 String 的内容进行比较
equals() 方法是通过内容值进行判断,同时区分大小写
- 1
public class Test{
public static void main(String[] args) {
String str1 = "hello";
String str2 = new String("hello");
String str3 = str2;
System.out.println("str1 == str2 -->" + (str1.equals(str2)));
System.out.println("str2 == str3 -->" + (str2==str3));
}
}
- 8
- 9
三、String 类两种对象实例化方式的区别
探讨直接赋值和使用标准的 new 调用构造方法完成实例化的区别之前,我们首先需要明白匿名对象就是已经开辟堆内存空间的并可以直接使用的对象
public class Test{
public static void main(String[] args) {
System.out.println("\"hello\" equals \"hello\" --> " + ("hello".equals("hello")) );
}
}
- 1
- 2
- 3
- 4
- 5
结果表明,一个字符串确实可以调用 String 类中的方法,也就证明了一个字符串就是一个 String 类的匿名对象
避免 NullPointerException
的比较操作
public class Test{
public static void main(String[] args) {
String input = null;
if(input.equals("hello")){
System.out.println("Hello Wrold !!!");
}
}
}
- 8
这里由于 input 的内容为 null,而 null 对象调用方法的结果将直接导致 NullPointerException
public class Test{
public static void main(String[] args) {
String input = null;
if("hello".equals(input)){
System.out.println("Hello Wrold !!!");
}
}
}
- 8
此时程序直接利用字符串常量调用 equals() 方法,因为字符串常量是一个 String 类的匿名对象,所以该对象永远不可能是 null,所以将不会出现NullPointerException
public class Test{
public static void main(String[] args) {
String str1 = "hello";
String str2 = "hello";
String str3 = "hello";
String str = new String("hello");
}
}
- 8
使用直接赋值的方式为 String 实例化:
从图中我们可知 String 使用直接赋值的方式之后,只要是以后声明的字符串内容相同,则不会再开辟新的内存空间
使用 new String 方式实例化对象:
一个字符串就是一个 String 类的匿名对象,而如果使用 new 关键字,不管如何都会开辟一个新的空间,此空间的内容还是 hello。所以 String str = new String("hello")
实际上是开辟了两个内存空间。
因此当我们对于字符串进行操作时,一般采用直接赋值的方法完成,而不考虑采用构造方法的方式完成。
四、常见面试题分析
- 请解释 String 类中
==
和equals()
方法比较的区别
(1)== 是 Java 提供的关系运算符,主要功能是进行数值相等判断的,如果用在了 String
对象上表示的是内存地址数值的比较
(2)equals()方法是由 String 提供的一个方法,此方法专门负责进行字符串内容的比较
- 1
- 2
- 3
- 请解释 String 类的两种对象实例化方式的区别:
(1)直接赋值(String str="字符串";):只会开辟一块堆内存空间,并且会自动保存
在对象池之中,以供下次重复使用。
(2)构造方法(String str=new String("字符串")):会开辟两块堆内存空间,其中有一块空间将成为垃圾,并且不会自动入池,但是用户可以使用 intern() 方法手工入池。
- 1
- 2
- 3
- String 类所采用的设计模式为共享设计模式
在JVM 的底层实际上会存在一个对象池(不一定只保存 String 对象),当代码中使用了直接赋值的方式定义了一个 String 类对象时,会将此字符对象所使用的匿名对象池保存,而后如果后续还有其他 String 类对象也采用了直接赋值的方式,并且设置了同样的内容的时候,那么将不会开辟新的内存空间,而是使用已有的对象进行引用的分配,从而继续使用。
关于共享设计模式的简单解释,这就好比在家中准备的工具箱一样,如果有一天需要用到螺丝刀,发现家里没有,那么肯定要去买一把新的,但是用完之后不可能丢掉,会将其放到工具箱中以备下次使用,而这个工具箱中的工具肯定可以为家庭中所有成员服务。