https://blog.csdn.net/isscollege/article/details/78398968java
https://www.jianshu.com/p/9819eb48716aide
String是final类,也就是不可变的。测试
String a = “abc”;ui
a = “xxx”;spa
实际上内存中“abc”、“xxx”都没变(每次赋值实际上都开辟了新的一块内存)。只是a的引用变了。.net
那么有个新的疑问,以下代码code
String a = “abc”;blog
a = “abcde”;内存
能够看到“abcde”内容里包含“abc”,那么“abc”会不会被复用呢?就是“abcde”、“abc”起始地址会不会同样呢,以下图这样:“abcde”取的是5个char,“abc”取的是3个char,前三个char“abc”是同样的?ci
a |
b |
c |
d |
e |
须要实际测试一下。
C:\Users\lenovo>java -version
java version "1.8.0_161"
Java(TM) SE Runtime Environment (build 1.8.0_161-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.161-b12, mixed mode)
import sun.misc.Unsafe; import java.lang.reflect.Field; public class StringAddressTest { static final Unsafe unsafe = getUnsafe(); static final boolean is64bit = true; public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, InterruptedException { String a = "abc"; String b = "abc"; String c = "abcde"; String d = "abcdefghigklmnopq"; System.out.println(a == b); // System.out.println("======hashCode======"); // System.out.println(a.getClass() + "@" + a.hashCode()); // System.out.println(b.getClass() + "@" + b.hashCode()); // System.out.println(c.getClass() + "@" + c.hashCode()); // System.out.println(c.getClass() + "@" + d.hashCode()); // // System.out.println("======System.identityHashCode======"); // System.out.println("a@" + System.identityHashCode(a) ); // System.out.println("b@" + System.identityHashCode(b) ); // System.out.println("c@" + System.identityHashCode(c) ); // System.out.println("d@" + System.identityHashCode(d) ); System.out.println("======Addresses======"); printAddresses("a:", a); printAddresses("b:", b); printAddresses("c:", c); printAddresses("d:", d); // TimeUnit.SECONDS.sleep(10000); } public static void printAddresses(String label, Object... objects) { System.out.print(label + ": 0x"); long last = 0; //获取偏移地址值 int offset = unsafe.arrayBaseOffset(objects.getClass()); //获取变量占用空间大小 int scale = unsafe.arrayIndexScale(objects.getClass()); switch (scale) { case 4: long factor = is64bit ? 8 : 1; final long i1 = (unsafe.getInt(objects, offset) & 0xFFFFFFFFL) * factor; System.out.print(Long.toHexString(i1)); last = i1; for (int i = 1; i < objects.length; i++) { final long i2 = (unsafe.getInt(objects, offset + i * 4) & 0xFFFFFFFFL) * factor; if (i2 > last) System.out.print(", +" + Long.toHexString(i2 - last)); else System.out.print(", -" + Long.toHexString(last - i2)); last = i2; } break; case 8: throw new AssertionError("Not supported"); } System.out.println(); } private static Unsafe getUnsafe() { try { Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); theUnsafe.setAccessible(true); return (Unsafe) theUnsafe.get(null); } catch (Exception e) { throw new AssertionError(e); } } }
true
======Addresses======
a:: 0x781eea450
b:: 0x781eea450
c:: 0x781eea480
d:: 0x781eea4b8
实际测试结果可见,
String a = "abc";
String b = "abc";
出现的是一样的结果
String c = "abcde";
String d = "abcdefghigklmnopq";
都是不一样的结果了。
也就是说字符串没有被复用。
请注意JDK版本,是否是别的版本也是这样的结果?不知道。