<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                ### String 在JAVA語言中有八種基本類型包裝類和一種比較特殊的類型String。這些類型為了使他們在運行過程中速度更快,更節省內存,都提供了一種常量池的概念。常量池就類似一個JAVA系統級別提供的緩存。因為String不可變的性質,因此Java內部實現了String常量池。當一個String被創建時,會先去常量池查看有沒有值相同的示例,有的話直接返回。節省了內存,加快了字符串的加載速度。不可變的對象也可以保證在并發中保持線程安全 其中String類型的常量池比較特殊。它的主要使用方法有兩種: * 直接使用雙引號聲明出來的String對象會直接存儲在常量池中。 * 如果不是用雙引號聲明的String對象,可以使用String提供的intern方法。intern 方法會從字符串常量池中查詢當前字符串是否存在,若不存在就會將當前字符串放入常量池中 ### 構造器 ![](https://img.kancloud.cn/6f/1a/6f1a725fa8e4b35231c6957501dfcb30_809x130.png) ![](https://img.kancloud.cn/37/bf/37bfbdc1d623d9e4b49b955369e2d1d5_807x278.png) ### 特性 * 字符串常量,實際上也是String對象 * 所有不是通過new創建的String都是放在常量池中 * String類型的對象是不可變的 * String實現了CharSequence接口 ### String對象創建方式 ``` String str1 = "abcd"; String str2 = new String("abcd"); ``` 這兩種不同的創建方法是有差別的,第一種方式是在常量池中拿對象,第二種方式是直接在堆內存空間創建一個新的對象。 只要使用new方法,便需要創建新的對象 ### 連接表達式+\(加號\) 1. 只有使用引號包含文本的方式創建的String對象之間使用“+”連接產生的新對象才會被加入字符串池中。 2. 對于所有包含new方式新建對象(包括null)的“+”連接表達式,它所產生的新對象都不會被加入字符串池中 ``` String str1 = "str"; String str2 = "ing"; String str3 = "str" + "ing"; String str4 = str1 + str2; System.out.println(str3 == str4);//false String str5 = "string"; System.out.println(str3 == str5);//true ``` ``` 1、 Sting s; //定義了一個變量s,沒有創建對象; 2、 = // 賦值,將某個對象的引用(句柄)賦給s ,沒有創建對象; 3、 “abc” //創建一個對象; 4、 new String(); // 創建一個對象。 ``` ### 常用方法 ![](https://img.kancloud.cn/5a/b8/5ab8d6a8f55ca52b9770a83d29d2e910_803x51.png) ![](https://img.kancloud.cn/4b/37/4b37298a0b771efcb49ff55e3d8761fc_806x82.png) ![](https://img.kancloud.cn/a0/05/a00569e48e560aec9f0ade81babc77e4_815x230.png) ![](https://img.kancloud.cn/f7/2a/f72a63d0e5f7a4ef4bd605273054180e_801x134.png) ![](https://img.kancloud.cn/07/19/07192e2aed8468e62dce058f9a1ad07c_847x618.png)![](https://img.kancloud.cn/e8/c0/e8c094e181420e87ccd4d5f8315a91dc_837x562.png)![](https://img.kancloud.cn/48/f6/48f6654f1f4bde0ef7dff769a029cf5f_818x145.png) * length 返回字符串長度 * isEmpty 判斷字符串是否為空 * charAt 根據索引位置獲取char * getChars 復制對應位置范圍的char到數組中 * equals, equalsIgnoreCase 對比順序依次為引用地址,char數組長度,char數組內容 * compareTo 對比字符串大小 * startsWith, endsWith 判斷前后綴 * hashCode 計算hash值, 公式為s\[0\]\*31^\(n-1\) + s\[1\]\*31^\(n-2\) + ... + s\[n-1\] * indexOf 查找首次出現的位置 * lastIndexOf 查找最后出現的位置 * substring 返回子串(舊版本是返回一個引用在父串的一個新串,節省重新分配內存。但實際如果子串引用了一個占用極大的父串,會因為子串一直被使用導致父串沒法被垃圾回收,新版本substring每次重新復制char數組) * concat 拼接字符串(拼接char數組,重新創建字符串) * replace 用新字符替換所有的舊字符(會先遍歷一次char數組,尋找時候存在,再去替換,避免每次都要分配char數組) * matches 判斷是否符合正則 (復用Pattern.matches\(\)方法) * contains 判斷是否包含子串(復用indexOf\(\)方法) * replaceFirst 只替換一次 * replaceAll 替換所有正則符合的地方 * split 按照正則分割字符串 * toLowerCase 返回小寫 * toUpperCase 返回大寫 * trim 去除前后空格 * toCharArray 重新復制char數組返回 * join\(CharSequence delimiter, CharSequence... elements\) ``` String.join(",", "you", "bao", "luo"); //out: you,bao,luo ``` * equals\(Object anObject\) String.equals\(\)代碼邏輯: 1. 判斷傳入的對象與當前對象是否為同一個對象,如果是就直接返回true; 2. 判斷傳入的對象是否為String,若不是則返回false\(如果為null也不成立\); 3. 判斷傳入的String與當前String長度是否一致,若不一致則返回false; 4. 循環對比兩個字符串的char\[\]數組,逐個對比字符是否一致,若不一致則直接返回false; 5. 循環結束沒有找到不匹配的則返回true; ``` JDK8源碼: public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) { String anotherString = (String)anObject; int n = value.length; if (n == anotherString.value.length) { char v1[] = value; char v2[] = anotherString.value; int i = 0; while (n-- != 0) { if (v1[i] != v2[i]) return false; i++; } return true; } } return false; } ``` * intern\(\):naive方法,直接返回常量池中的引用 當調用intern\(\)方法時,JVM會在常量池中通過equals\(\)方法查找是否存在等值的String,如果存在則直接返回常量池中這個String對象的地址;如果不存在則會創建等值的字符串放入常量池\(即等值的char\[\]數組字符串,但是char\[\]是新開辟的一份拷貝空間\),然后再返回這個新創建空間的地址; 注意:String的String Pool是一個固定大小的Hashtable,默認值大小長度是1009 在常量池查找等值String時,通常不止一個字符串而是多個字符串因此效率會比較低,另外為保證唯一性,需要有鎖的介入; ``` String str1 = "ab"; String str2 = new String("ab"); System.out.println(str1== str2);//false System.out.println(str2.intern() == str1);//true System.out.println(str1== str2);//false str2 = str2.intern(); System.out.println(str1== str2);//true ``` ### 知識點 * 在調用x.toString\(\)的地方可以用""+x替代; * 字符串的+拼接操作 ``` public static void main(String[] args) throws InterruptedException { String s = "a"; String st = s + "b" + "c"; } javap out====> Code: stack=3, locals=3, args_size=1 0: ldc #19 // String a 2: astore_1 3: new #21 // class java/lang/StringBuilder 6: dup 7: aload_1 8: invokestatic #23 // Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String; 11: invokespecial #29 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V 14: ldc #32 // String b 16: invokevirtual #34 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 19: ldc #38 // String c 21: invokevirtual #34 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 24: invokevirtual #40 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 27: astore_2 28: return ``` * StringBuffer是線程安全操作 ``` public synchronized StringBuffer append(String str) { toStringCache = null; super.append(str); return this; } ``` * StringBuilder非線程安全 ``` public StringBuilder append(String str) { super.append(str); return this; } ``` ``` System.err.println("hello,world"); ##hello,world實際是String對象 ``` ### printf格式化輸出 ![](https://img.kancloud.cn/2d/27/2d2767f1acc42cc4544c1ace11ec4e7c_761x471.png) **FAQ** 1. String str1 = "abc"; System.out.println\(str1 == "abc"\); 步驟: a&gt; 棧中開辟一塊空間存放引用str1; b&gt; String池中開辟一塊空間,存放String常量"abc"; c&gt; 引用str1指向池中String常量"abc"; d&gt; str1所指代的地址即常量"abc"所在地址,輸出為true; 1. String str2 = new String\("abc"\); System.out.println\(str2 == "abc"\); 步驟: a&gt; 棧中開辟一塊空間存放引用str2; b&gt; 堆中開辟一塊空間存放一個新建的String對象"abc"; c&gt; 引用str2指向堆中的新建的String對象"abc"; d&gt; str2所指代的對象地址為堆中地址,而常量"abc"地址在池中,輸出為false; 注意:對于通過new產生的對象,會先去常量池檢查有沒有 “abc”,如果沒有,先在常量池創建一個 “abc” 對象,然后在堆中創建一個常量池中此 “abc” 對象的拷貝對象; 2. String s2 = new String\(“Hello”\); 產生幾個對象? 首先,在jvm的工作過程中,會創建一片的內存空間專門存入string對象。我們把這片內存空間叫做string池; String s2 = new String\(“Hello”\);jvm首先在string池內里面看找不找到字符串"Hello",如果找到不做任何事情;否則創建新的string對象,放到string池里面。由于遇到了new,還會在內存Heap上(不是string池里面)創建string對象存儲"Hello",并將內存上的(不是string池內的)string對象返回給s2。 Re: 如果常量池中原來沒有“Hello”, 則創建兩個對象。如果原來的常量池中存在“Hello”時,就是一個對象; 3. 其它 \`\`\` String str1 = "a"; String str2 = "b"; String str3 = str1 + "b"; //str1 和 str2 是字符串常量,所以在編譯期就確定了。 //str3 中有個 str1 是引用,所以不會在編譯期確定。 //又因為String是 final 類型的,所以在 str1 + "b" 的時候實際上是創建了一個新的對象,在把新對象的引用傳給str3 final String str1 = "a"; String str2 = "b"; String str3 = str1 + "b"; //這里和\(3\)的不同就是給 str1 加上了一個final,這樣str1就變成了一個常量。 //這樣 str3 就可以在編譯期中就確定了 \`\`\` 【參考資料】 [https://tech.meituan.com/in\_depth\_understanding\_string\_intern.html](https://tech.meituan.com/in_depth_understanding_string_intern.html) \#\#【深入解析String\#intern -- 美團】 [http://rednaxelafx.iteye.com/blog/774673](http://rednaxelafx.iteye.com/blog/774673)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看