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版本,是否是別的版本也是這樣的結果?不知道。