java(11): Object 类学习 和 String 陷阱分析

1. 相等性的比较(==)

    a. 对于原生数据类型来说,比较的是左右两边的值是否相等。

    b. 对于引用类型来说,比较左右两边的引用是否指向同一个对象,或者说左右两边的引用地址是否相同。

2. Object 类是所有对象的父类 。

3. 

public class StringTest {
    public static void main(String[] args) {
        Object object = new Object();
        System.out.println(object);
        System.out.println(object.toString());
    }
}
// output
java.lang.Object@f5f2bb7
java.lang.Object@f5f2bb7

    当我们使用 System.out.println() 打印一个引用类型变量时,实际上会打印出引用所指向对象的 toString() 方法的返回值,因为每个类都直接或间接地继承自 Object,而 Object 类中定义了 toString(),因此每个类都有 toString() 方法。

public class StringTest {
    public static void main(String[] args) {
        String string = "ym";
        System.out.println(string);
    }
}
// output
ym

这是因为 String 对象重写了 Object 中的 toString() 方法,重写之后就是返回这个对象的本身。

// JDK 中 Stirng 中 toString() 方法
/**
* This object (which is already a string!) is itself returned.
*
* @return  the string itself.
*/
public String toString() {
    return this;
}

再看看 Object 对象中的 toString() 源码:

public String toString() {
    return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

通过源码我们就知道为什么上面返回的是 java.lang.Object@f5f2bb7。

4.

String 是常量,其一旦被创建便无法被改变。当使用 "+" 拼接时,就会创建新的对象,而不是往原有的对象拼接。

5.

下面看一段代码,然后详细分析一下:

public class StringTest {
    public static void main(String[] args) {
        Object object = new Object();
        Object object2 = new Object();
        System.out.println("1: " + (object == object2));

        String str = new String("ym");
        String str2 = new String("ym");
        System.out.println("2: " + (str == str2));

        String str3 = "ym";
        String str4 = "ym";
        System.out.println("3: " + (str3 == str4));

        String str5 = new String("ym");
        String str6 = "ym";
        System.out.println("4: " + (str5 == str6));

        String str7 = "ym";
        String str8 = "y";
        String str9 = "m";
        System.out.println("5: " + (str7 == str8 + str9));

        System.out.println("6: " + (str7 == "y" + "m"));
    }
}
// output
1: false
2: false
3: true
4: false
5: false
6: true

结果分析:

a. 1 和 2 都很容易,因为它们指向的对象不同,所以其引用地址不一样,结果自然就为 false。

b. 3 的结果为 true。这是因为 Java 中有一个 String Pool (常量池)的概念,每次通过 string = "abc"(采用字面值方式赋值) 这种方式在代码中创建 String 对象的时候会首先在 String Pool 中查找有没有这个相同的对象,如果没有就创建一个新的,如果有就不创建新的对象,直接将该对象的地址赋值给相应的引用类型变量。所以上面的 str3 创建了 "ym" 之后,str4 指向的也是同一个字符串对象,导致结果为 true。

c. String s = new String("ym")创建过程:①首先在 String pool 中查找有没有 "ym" 这个字符串对象,如果有,就不用在 String Pool 中再次创建这个对象了,直接在堆(heap)中创建一个 "ym" 字符串对象,然后将堆中这个对象的地址返回给引用变量 s,导致 s 指向堆中创建的这个字符串对象。②如果在 String Pool 中没有,则先在 String Pool 中创建这个对象,然后再在堆中(heap)创建一个 "ym" 对象,最后将堆中的这个对象的地址赋值给引用变量 s,导致 s 指向堆中创建的这个字符串对象。所以在结果 4 中一个指向的是堆中的“ym”对象,一个指向的是栈中(stack)String Pool 中的“ym”对象,它们并不是同一个对象,所以结果返回 false。

d. str7 指向的是 String Pool 中的 "ym" 对象,而 str8 +str9 虽然内容也为 "ym",但是这个 "ym" 对象是在堆中,所以 str8 +str9 是堆中 “ym”对象的内存地址,所以结果为 false。

e. str7 指向的是 String Pool 中的 "ym" 对象,而 “y”+“m”创建的“ym”对象也是在 String Pool 中,而由于 String Pool 中已经存在了这个对象,所以它们指向的是同一个 String 对象。故为true。

6. String 中的 intern() 方法

比如

String str ="ym".intern()

这个方法意思就是,目的是将 "ym" 对象的地址赋值给 str,而创建这个对象时,会首先在 String Pool 中找有没有这个对象,如果有,就直接指向这个对象。如果没有就在 String Pool 中创建这个对象之后再指向它。看个例子:

String str1 = "ym";
String str2 = new String("ym");
String str3 = str2.intern();
System.out.println(str1 == str3);  // true (因为 str1 和 str3 都是指向 String pool 中的 "ym" 对象)
System.out.println(str2 == str3);  // false (因为 str2 指向的是堆中的 "ym" 对象,而 str3 指向的是 String Pool 中的 "ym")

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值