- String对象的特点
- String对象创建的两种方式
- 方式一:通过字符串常量的方式创建
- 方式二:通过new对象的方式创建
- String对象的“==”和“equals”
- String对象的比较到底是用“==”还是equals呢?
- "testString"为什么可以通过(.点)调出equals方法
- 分析以下程序创建了几个对象
- String对象重写了toString方法
String是JDK中内置的一个类:java.lang.string
- 1.String表示字符串类型,属于引用数据类型,不属于基本数据类型.
- 2.Java中使用双引号括起来的都是String对象。例如:“abc”、“lei”、“hello world!”,这就是三个对象。
- 3.Java中规定,双引号括起来的字符串是不可变的,也就是说“abc”从出生到消亡双引号里的内容是不会变的,不可能变成“abcd”,也不可能变成“ab”。
- 4.字符串都是直接存储在“方法区”的字符串常量池当中的。
- 5.为什么把字符串存储在“字符串常量池”当中呢。因为字符串在实际开发中使用的很频繁,为了提供效率所以存储在“字符串常量池中”。
//方式一:通过常量的方式创建string对象 //以下两行代码表示底层创建了3个字符串对象,都在字符串常量池当中。 String s1 = "abcdef"; String s2 = "abcdef" + "xy";
方式一 的内存图(截图于老杜JAVA),s1和s2的内存地址指向了字符串常量池中的字符串。因为s2是“abcdef”和“xy”的拼接,又因为“abcdef”,s1已经创建了,所以s2直接拿过来。这也就是为什么要把字符串存储在方法区的字符串常量池中的原因,第一次创建了,第二次使用时就不用创建了直接拿过来用。
//通过new的方式创建String对象。
//分析:结合以上内容可以先分析s3的“xy”从哪来。
//提示:凡是“”括起来的都在字符串常量池中。
//注意:new对象的时候一定在堆内存中开辟空间。
String s3 = new String("xy");
方式二的内存图,s3在内存中存在的形式就是,栈中的s3的内存地址指向堆中的String对象,堆中的String对象中的内存地址又指向方法区中“xy”的内存地址。
如果堆里面new的是一个User对象,User对象里有一个String类型的name属性,则User的name里存储的并不是具体的字符串,而是存储的是字符串在字符串常量池中的内存地址。
思考1,方式一创建的String对象中(s1 == s2)的结果。要知道“==”判断的是内存地址
public static void main(String[] args) {
String s1 = "hello";
String s2 = "hello";
System.out.println(s1 == s2);
}
分析,字符串“hello”存储在方法区的字符串常量池中,栈中的s1和s2存储的都是“hello”的内存地址。字符串常量池中有的常量,不会被重复创建。所以s1 == s2为true。
思考2,方式二 new的String对象中(x == y)的结果。要知道new出来的对象在堆中开辟空间。且“==”判断的是内存地址。
public static void main(String[] args) {
String x = new String("xyz");
String y = new String("xyz");
System.out.println(x == y);
}
分析,既然new出来的对象在堆内存中开辟空间,也就意味着每一个new出来的对象都有一个单独的堆内存地址。虽然堆中的对象都指向的是“xyz”中的字符串常量池中的内存地址,但栈中的x和y都指向x和y在堆内存中的不同的堆内存地址。所以xy为false。
于是乎我们得出结论,字符串对象之间的比较不能使用“”。
"=="不保险,应该调用String对象的equals方法
翻看源码可知Object的equals的方法默认也是使用“==”做比较。
那咱们再来看看String对象的equals方法(String对象重写了equals方法)
所以以上案例中x和y的比较应该使用equals。
因为“testString”就是一个String字符串对象,只要是对象就能调用方法。
String k = new String("testString");
System.out.println("testString".equals(k));
System.out.println(k.equals("testString"));
以上两种使用equals方式做比较都可以,但是推荐使用k.equals(“testString”)。因为如果k为null的话,k.equals(“testString”)就会报空指针异常。使用为空的对象调用方法就会出错。
public class StringTest03 {
public static void main(String[] args) {
String s1 = new String("hello");
String s2 = new String("hello");
}
}
String对象重写了toString方法
public class StringTest04 {
public static void main(String[] args) {
String s1 = "hello world";
System.out.println(s1.toString());
byte[] bytes = {97,98,99};
String s2 = new String(bytes);
System.out.println(s2.toString());
System.out.println(s2);
}
}
所以 System.out.println(s2.toString());
System.out.println(s2);输出的是同样的结果。



