描述
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
网友评论