首頁  >  問答  >  主體

Java: 不同String 相加在内存里的分布?

    String str1 = "a";
    String str2 = "b";
    String str3 = "ab";
    String str4 = new String("a");
    String str5 = new String("b");
    String str6= new String("ab");
    
    
    String plus1 = str1 + str2; 
    String plus2 = str1 + "b"; 
    String plus3 = str4 + "b";
    String plus4 = "a" + "b";
    String plus5 = str4 + str5;
    String plus6 = str4 + str2;

string相加有上面的6种情况
我想弄清楚各种情况的区别,我知道的是plus4都是在栈区,所以结果是一个字符串常量池里的常量,但是其他情况呢?
另外,我打印plus1~plus6的地址或者hashcode,发现都是一样的,怎么回事?

迷茫迷茫2712 天前752

全部回覆(3)我來回復

  • PHP中文网

    PHP中文网2017-04-18 10:32:17

    一樓回答太籠統,而且拋開JVM和JDK版本談內存分配都是耍流氓。

    以提問的為例:

    String str1 = "a";
    String str2 = "b";
    String str3 = "ab";

    這種直接定義字串,JVM認為字串是不變量,也就是執行緒安全的,因為這種字串直接分配在方法區的常數池中.

    String str4 = new String("a");
    String str5 = new String("b");
    String str6= new String("ab");

    有new關鍵字,說明這種字串是分配在堆上.可以使用以下方法驗證:

    public static void main(String[] args) {
        String str1 = "a";
        String str2 = "b";
        String str3 = "ab";
        
        String str4 = new String("a");
        String str5 = new String("b");
        String str6= new String("ab");
        
        System.out.println(str1 == str4);   // false,说明str1和str4的内存地址不一样,一个在方法区,一个在堆.
        System.out.println(str1 == str4.intern());  // true,str4存入常量池后并没有重新创建一块内存,而是使用了已有的常量句柄.
        }

    回答為什麼plus1~6的hashcode一樣,是因為你沒有去重寫String的hashcode方法。而String預設hashcode的實作為:

    @Override public int hashCode() {
        int hash = hashCode;
        if (hash == 0) {
            if (count == 0) {
                return 0;
            }
            for (int i = 0; i < count; ++i) {
                hash = 31 * hash + charAt(i);
            }
            hashCode = hash;
        }
        return hash;
    }

    只是對字面常數做了處理,而plus1~6的字面常數一樣,所以hashcode值當然一致。然後hashcode一致,不代表它們在jvm分配的記憶體位址一致。

    回覆
    0
  • ringa_lee

    ringa_lee2017-04-18 10:32:17

    相同字串在記憶體中只有一個實例

    ------------------------------分割線----------------

    本答案過於籠統,且有誤導之嫌,請大家移步正一兄的回答

    回覆
    0
  • 大家讲道理

    大家讲道理2017-04-18 10:32:17

    樓上說的對,相同字串字面量在方法區中只會有一個值。這個也就是常說的string和stringbuffer的用法區別。

    下面我補充:
    String str4 = new String("a");
    「a」字面量是儲存在jvm的方法區。
    str4這個物件是存放在堆中。
    上面這句話意思就有2個記憶體位址被分配。
    而棧中儲存的是8中基本型別和returnAddress、reference,字串是不會儲存在棧中。
    關於hashcode用法呢,就是用來配對和定位的。你可以去自己去百度hashcode 和 == 和 equals的差別。
    而且,plus1-6的記憶體位址一定是不一樣的。我不知道你怎麼發現是一樣的。 。 。

    如果有什麼理解的不對的,忘各位大牛指點一二。

    回覆
    0
  • 取消回覆