首页 StringTable学习
文章
取消

StringTable学习

习题一(JDK1.8)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class TestStringTable {

    //运行环境JDK1.8
    public static void main(String[] args) {
        String s1 = "a";
        String s2 = "b";
        String s3 = "a" + "b";
        String s4 = s1 + s2;
        String s5 = "ab";
        String s6 = s4.intern();
        //问
        System.out.println(s3 == s4);
        System.out.println(s3 == s5);
        System.out.println(s3 == s6);

        String x2 = new String("c") + new String("d");
        String x1 = "cd";
        x2.intern();
        //问
        System.out.println(x1 == x2);

        String y2 = new String("e") + new String("f");
        y2.intern();
        String y1 = "ef";
        //问
        System.out.println(y1 == y2);
    }

}

输出答案

展开查看 false
true
true
false
true

解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
public class TestStringTable {

    //运行环境JDK1.8
    //代码运行时,常量池加载到运行时常量池中,还没有变为Java中的对象
    //执行String s1 = "a"时,会把"a"加入到串池中(前提hash值不存在,存在则不增加)
    //HashTable不能扩容,可通过虚拟机参数设置
    public static void main(String[] args) {
        String s1 = "a";
        //串池 ["a"] s1为串池中"a"的地址
        String s2 = "b";
        //串池 ["a","b"] s2为串池中"b"的地址
        String s3 = "a" + "b";
        //此处编译优化,等价于 s3 = "ab"; 串池 ["a","b","ab"] s3为串池中"ab"的地址
        String s4 = s1 + s2;
        //使用StringBuild().append拼接,再通过new String()生成对象,所以 s4 = new String("ab");
        String s5 = "ab";
        //串池已存在"ab",s3为串池中"ab"的地址
        String s6 = s4.intern();
        //把 s4 = new String("ab"); 手动加入串池,由于串池已经存在"ab",所以失败,s4 = new String("ab");
        //而s6为串池中"ab"的地址
        //问
        System.out.println(s3 == s4);//false
        System.out.println(s3 == s5);//true
        System.out.println(s3 == s6);//true

        String x2 = new String("c") + new String("d");
        //使用StringBuild().append拼接,再通过new String()生成对象,所以 x2 = new String("cd");
        String x1 = "cd";
        //串池 ["cd"] x1为串池中"cd"的地址
        x2.intern();
        //把 x2 = new String("cd"); 手动加入串池,由于串池已经存在"cd",所以失败,x2 = new String("cd");
        //问
        System.out.println(x1 == x2);//false

        String y2 = new String("e") + new String("f");
        //使用StringBuild().append拼接,再通过new String()生成对象,所以 y2 = new String("ef");
        y2.intern();
        //把 y2 = new String("ef"); 手动加入串池,由于串池不存在"ef",所以成功,串池 ["ef"],y2为串池中"ef"的地址;
        String y1 = "ef";
        //串池 ["ef"] y1为串池中"ef"的地址
        //问
        System.out.println(y1 == y2);//true
    }

}

习题二(JDK1.6)

思考在JDK1.6环境下执行习题一代码

输出答案

展开查看 false
true
true
false
false

解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
public class TestStringTable {

    //运行环境JDK1.6
    //代码运行时,常量池加载到运行时常量池中,还没有变为Java中的对象
    //执行String s1 = "a"时,会把"a"加入到串池中(前提hash值不存在,存在则不增加)
    //HashTable不能扩容,可通过虚拟机参数设置
    public static void main(String[] args) {
        String s1 = "a";
        //串池 ["a"] s1为串池中"a"的地址
        String s2 = "b";
        //串池 ["a","b"] s2为串池中"b"的地址
        String s3 = "a" + "b";
        //此处编译优化,等价于 s3 = "ab"; 串池 ["a","b","ab"] s3为串池中"ab"的地址
        String s4 = s1 + s2;
        //使用StringBuild().append拼接,再通过new String()生成对象,所以 s4 = new String("ab");
        String s5 = "ab";
        //串池已存在"ab",s3为串池中"ab"的地址
        String s6 = s4.intern();
        //把 s4 = new String("ab"); 复制一份手动加入串池,由于串池已经存在"ab",所以失败,s4 = new String("ab");
        //而s6为串池中"ab"的地址
        //问
        System.out.println(s3 == s4);//false
        System.out.println(s3 == s5);//true
        System.out.println(s3 == s6);//true

        String x2 = new String("c") + new String("d");
        //使用StringBuild().append拼接,再通过new String()生成对象,所以 x2 = new String("cd");
        String x1 = "cd";
        //串池 ["cd"] x1为串池中"cd"的地址
        x2.intern();
        //把 x2 = new String("cd"); 复制一份手动加入串池,由于串池已经存在"cd",所以失败,x2 = new String("cd");
        //问
        System.out.println(x1 == x2);//false

        String y2 = new String("e") + new String("f");
        //使用StringBuild().append拼接,再通过new String()生成对象,所以 y2 = new String("ef");
        y2.intern();
        //把 y2 = new String("ef"); 复制一份手动加入串池,由于串池不存在"ef",所以成功,串池 ["ef"],y2 = new String("cd");
        String y1 = "ef";
        //串池 ["ef"] y1为串池中"ef"的地址
        //问
        System.out.println(y1 == y2);//true
    }

}

总结

1、理解串池的概念和变量存放位置

2、在JDK6中data.intern()方法是复制一份data出来执行加入串池的操作,加入成功或失败都返回串池中的数据

3、在JDK8中data.intern()方法是直接data执行加入串池的操作,加入成功data指向串池中数据的地址,失败则对象不变,加入成功或失败都返回串池中的数据

4、JDK6串池用的永久代,JDK8串池用的堆空间

5、-XX:StringTableSize=1009 可以设置StringTable的桶个数,最小是1009

JVM内存结构

本文由作者按照 CC BY 4.0 进行授权