thinking in java test5.1练习(1)(2)

练习(1)题目:创建一个类,它包含一个未初始化的String引用。验证该引用被Java初始化成了null。
代码如下:

public class Test5_1_1 {
    public static void main(String[] args){
        Test t = new Test();
        System.out.println(t.str);
    }
}
class Test{
    String str;
}

这里写图片描述

打开源码查看一下:

 /**
     * Initializes a newly created {@code String} object so that it represents
     * an empty character sequence.  Note that use of this constructor is
     * unnecessary since Strings are immutable.
     */
    public String() {
        this.value = "".value;
    }

我们发现如果没有给String类初始化内容,系统会默认把“”的值赋给它,也就是null。

练习(2)题目:创建一个类,它包含一个在定义时就被初始化了的String域,以及另一个通过构造器初始化的String域。这两种方式有何差异?
代码如下:

class Test{
    String str = "123";
    String string =new String("234");
}

没差异吗?当然有差异了。
jvm对string,有一个专门的string pool(字符串池)来存储,我们看下面这个例子:

public static void main(String[] args){
        String s1 = "abc";
        String s2 = "abc";
        System.out.println(s1==s2);//结果是true
    }

粗看似乎打印的结果应该是false,因为==在比较引用时比较的是地址,但程序运行的结果是true,因为s1和s2两个引用指向的地址是同一个。
当你用String s1 = “abc”声明一个字符串时,jvm会先在字符串池里检查是否存在“abc”这个字符串,若存在,则指向它,不存在,则创建一个“abc”,再指向它。所以这里s1和s2指向的是同一个字符串。(jvm这么做是为了节省内存开销)。

而当我们String str = new String(“234”);时,首先,在堆里创建一个String对象,然后str指向这个对象。同时,jvm会检查字符串池,若字符串池中有“234”,就把这个字符串交给这个新建出来的对象持有,如果没有,则在字符串池中创建一个新字符串“234”,再把它交给对象。要注意的是,不管在创建对象时字符串池中有木有“234”,str始终指向新创建的对象,也就是str的值是对象堆空间的地址。至于字符串池中对象“234”,的地址,则存放在堆中。如图所示:
这里写图片描述
看代码:

public static void main(String[] args){
        String s1 = "abc";
        System.out.println(s1 == new String("abc"));//打印结果是false
    }

所以两种方式,一个是放在单独管理的字符串池里,一个是放在堆里开辟的对象空间里。是有根本区别的。

PS:一个经典面试题:
String s=new String(“abc”);
String s1=”abc”;
String s2=new String(“abc”);
上段代码究竟产生了几个对象?
我们来分析程序运行过程:首先声明引用s,在堆中创建一个新的String对象,s指向这个对象,与此同时,检测字符串池中有木有“abc”,发现没有,就创建一个。
此时,已经创建了两个对象。
然后第二行代码:String s1 = “abc”;jvm检查发现字符串池中有“abc”了,于是直接将s1指向它,这句代码没有创建新对象。
第三行代码,同第一行一样,声明引用s2,创建新对象,s2指向新对象,同时检查字符串池中有没有“abc”,发现有,就将起地址给新对象。
所以答案是三个对象。
当然如果在面试中遇到这个问题,我们也可以耍一下小聪明,说两个或三个,因为我们不清楚在这三行代码的前文,是否已经在字符串池中创建了“abc”对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值