[源碼]String StringBuffer StringBudlider(1String部分),stringbuffer源碼
String /** The value is used for character storage. */ private final char value[]; /** The offset is the first index of the storage that is used. */ private final int offset; //第一個元素 /** The count is the number of characters in the String. */ private final int count; /** Cache the hash code for the string */private int hash; // Default to 0 雜湊碼 /** use serialVersionUID from JDK 1.0.2 for interoperability */private static final long serialVersionUID = -6849794470754667710L; 這裡有一個問題:為什麼final的東西沒有直接初始化但編譯不報錯? 只要在 對象 初始化OK之前給它賦值就行 。 你可以在 顯示初始化—隱式初始化-初始化塊初始化-構造器任何一個地方給它初始化,編譯就不會報錯 說到String就不得不說一個事,叫做記憶體配置圖解記憶體管理Java記憶體配置與管理是Java的核心技術之一,之前我們曾介紹過Java的記憶體管理與記憶體泄露以及Java記憶體回收方面的知識,今天我們再次深入Java核心,詳細介紹一下Java在記憶體配置方面的知識。一般Java在記憶體配置時會涉及到以下地區: ◆寄存器:我們在程式中無法控制 ◆棧:存放基本類型的資料和對象的引用,但對象本身不存放在棧中,而是存放在堆中(new 出來的對象) ◆堆:存放用new產生的資料 ◆靜態域:存放在對象中用static定義的靜態成員 ◆常量池:存放常量◆非RAM儲存:硬碟等永久儲存空間 首先是 學基礎的程式員們最常提到的三塊地兒: 棧記憶體 堆記憶體 方法區Stack棧記憶體 電腦中用來存放 非靜態變數 的地區, Stack負責 你在建立非靜態變數時,讓 這個東西進棧 ,當 這個變數出了範圍 , Stack 再讓它出棧。 靜態變數 是儲存在 方法區靜態地區的。Heap 堆記憶體 堆記憶體 裡邊可以開闢空間 指派至,對象的首地址 賦值給 引用變數,這個就是Java裡邊的指標,這幾乎是唯一一塊受GC管理的地兒! 方法區 方法區裡邊 不僅放著方法而且放著靜態變數。裡邊有這麼幾塊地區比較重要: 方法區靜態地區 方法區非靜態地區 常量池 方法區靜態/非靜態地區 存的是什麼大家可以看我的另一篇博文://網址 常量池的話自然存的是常量 比如說 int a= 10; //編譯器就會去常量池找 有沒有10,如果之前用過就直接拿來,如果沒用過就 在常量池建立 10這個東西 但是 要注意的是 String的對象 也可以是常量: String st=”123”; //這個就是String最特殊的地方 大家注意一下 String就這麼兩種表達方式: 這個地方最容易出的問題就是 == equals 的問題== 與 equals方法 的區別 == 比較的是地址值 equals比較的也是地址值(更確切的說是hashCode),但是String裡邊重寫了這個方法,比較的是具體內容的值
public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) { String anotherString = (String)anObject; int n = count; if (n == anotherString.count) { char v1[] = char v2[] = anotherString. int i = offset; int j = anotherString.offset; while (n-- != 0) { //直接比較的是每個字元 if (v1[i++] != v2[j++]) return false; } return true; } } return false; }
字串拼接 學這塊內容 大家務必搞清楚每一步 這些變數 常量 對象 在記憶體上的變化
String s1 = "hello"; String s2 = "world"; String s3 = "helloworld"; System.out.println(s3 == s1 + s2); //false,s1+s2是一個新的String的地址的引用 s3.equals((s1 + s2)); System.out.println(s3 == "hello" + "world");//true,拼接起來的是常量池中找到的 s3.equals("hello" + "world");
現在大家只要知道 凡是有變數參加的字串拼接 拼出來的東西 一定是 new 出來的對象 若都是字串常量的拼接 則還是直接去常量池找的常量 //這個東西我留著專門寫個東西介紹什麼叫做 編譯期確定下來了 假如你這麼寫:
String a = "ab"; final String bb = "b"; /編譯時間已經放入常量池 String b = "a" + bb; System.out.println((a == b)); //result = true
方法返回
String a = "ab"; final String bb = getBB(); String b = "a" + bb; System.out.println((a == b)); //result = false private static String getBB() { return "b"; }
這兩個東西我放到編譯期確定下來了這篇文章給大家分析一下 2016-10-21 更新