關於字符串的實驗(abc和abcde的起始地址是否同樣?)

參考網頁

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

 

須要實際測試一下。

試驗

JDK版本

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

分析1

實際測試結果可見,

    String a = "abc";
    String b = "abc";

出現的是一樣的結果

    String c = "abcde";
    String d = "abcdefghigklmnopq";

都是不一樣的結果了。

也就是說字符串沒有被複用。

分析2

請注意JDK版本,是否是別的版本也是這樣的結果?不知道。

相關文章
相關標籤/搜索