String内部原理

2020-03-07  本文已影响0人  紫色红色黑色

描述

String内部是final修饰的char[]。下文定义方法获取String内部char[]的hashCode,验证不同的String对象内部char[]是否一致

代码

private static int showStringInternalCharArrayHashCode(String s) {
    Field value = null;
    try {
        value = String.class.getDeclaredField("value");
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    }

    if (value != null) {
        value.setAccessible(true);
        try {
            return value.get(s).hashCode();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
    return 0;
}
public static void main(String[] args) {

    String a = "abc";
    String b = "abc";
    String c = new String("abc");

    System.out.println("a.value:" + showStringInternalCharArrayHashCode(a));
    System.out.println("b.value:" + showStringInternalCharArrayHashCode(b));
    System.out.println("c.value:" + showStringInternalCharArrayHashCode(c));
    System.out.println("a:" + System.identityHashCode(a));
    System.out.println("b:" + System.identityHashCode(b));
    System.out.println("c:" + System.identityHashCode(c));

    // a.value:1595428806
    // b.value:1595428806
    // c.value:1595428806
    // a:1072408673
    // b:1072408673
    // c:1531448569
}

由结果看出变量a、b、c各自的内部char[]是同一个数组。a和b是因为从常量池中取出字符串,该字符串本就是同一个对象。c是因为String构造函数中将入参的char[]赋值给对象。可以从字节码中看出。

// #2定位到类常量池,在定位到字符串常量池中常量推送至操作数栈顶,
0: ldc           #2                  // String abc
// 存储变量到局部变量表下标1处
2: astore_1
3: ldc           #2                  // String abc
5: astore_2
// 堆中创建对象,对象引用推入栈顶
6: new           #3                  // class java/lang/String
// 复制栈顶元素
9: dup
// 常量池中常量推入栈顶
10: ldc           #2                  // String abc
// 调用构造函数初始化,参数对象引用和常量
12: invokespecial #4                  // Method java/lang/String."<init>":(Ljava/lang/String;)V
// 对象创建完毕存储到局部变量表下标3处
15: astore_3
public static void main(String[] args) {

    String a = "abc";
    String b = "aabc".substring(1);

    System.out.println("a.value:" + showStringInternalCharArrayHashCode(a));
    System.out.println("b.value:" + showStringInternalCharArrayHashCode(b));
    System.out.println("a:" + System.identityHashCode(a));
    System.out.println("b:" + System.identityHashCode(b));

    b = b.intern();

    System.out.println("a.value:" + showStringInternalCharArrayHashCode(a));
    System.out.println("b.value:" + showStringInternalCharArrayHashCode(b));
    System.out.println("a:" + System.identityHashCode(a));
    System.out.println("b:" + System.identityHashCode(b));

//        a.value:1595428806
//        b.value:1072408673
//        a:1531448569
//        b:1867083167
//        a.value:1595428806
//        b.value:1595428806
//        a:1531448569
//        b:1531448569

}

由结果看出,变量a、b不是同一个对象,内部char[]也不是同一个数组。调用intern()后,a、b变成同一个对象了。

引用

https://dzone.com/articles/java-string-tutorials
https://dzone.com/articles/string-memory-internals

上一篇 下一篇

猜你喜欢

热点阅读