java String 深入理解


  • 說出下面程序的輸出
class StringEqualTest {

    public static void main(String[] args) {
            String s1 = "Programming";
                String s2 = new String("Programming");
                String s3 = "Program" + "ming";
                String s4=new String(s2);
         String s5 = "Programming";
                System.out.println(s1 == s2);//false
                System.out.println(s4 == s2);//false
                System.out.println(s1 == s3);//true
                System.out.println(s1 == s1.intern());//true } }

解釋:

在此引入常量池這個概念:
常量池(constant pool)指的是在編譯期被確定,並被保存在已編譯的.class文件中的一些數據。它包括了關於類、方法、接口等中的常量,也包括字符串常量

首先,我們要知道Java會確保一個字符串常量只有一個拷貝。 

因為例子中的s1和s3中的
Programming”都是字符串常量,它們在編譯期就被確定了,所以s1==s3為true;而”Program”和”ming”也都是字符 串常量,當一個字符串由多個字符串常量連接而成時,它自己肯定也是字符串常量,所以s3也同樣在編譯期就被解析為一個字符串常量,所以s3也是常量池中 ”kvill”的一個引用。 

所以我們得出s5==s1==s2; 

用new String() 創建的字符串不是常量,不能在編譯期就確定,所以new String() 創建的字符串不放入常量池中,它們有自己的地址空間。

所以有s2!=s4

String對象的intern方法會得到字符串對象在常量池中對應的版本的引用(如果常量池中有一個字符串與String對象的equals結果是true),如果常量池中沒有對應的字符串,則該字符串將被添加到常量池中,然后返回常量池中字符串的引用。

再補充介紹一點:存在於.class文件中的常量池,在運行期被JVM裝載,並且可以擴充。String的intern()方法就是擴充常量池的一個 方法;當一個String實例str調用intern()方法時,Java查找常量池中是否有相同Unicode的字符串常量,如果有,則返回其的引用, 如果沒有,則在常量池中增加一個Unicode等於str的字符串並返回它的引用;

案例

 

String s0= “kvill”; 
String s1=new String(”kvill”); 
String s2=new String(“kvill”); 
System.out.println( s0==s1 ); 
System.out.println( “**********” ); 
s1.intern(); 
s2=s2.intern(); //把常量池中“kvill”的引用賦給s2 
System.out.println( s0==s1); 
System.out.println( s0==s1.intern() ); 
System.out.println( s0==s2 ); 
結果為: 

false 
********** 
false //雖然執行了s1.intern(),但它的返回值沒有賦給s1 
true //說明s1.intern()返回的是常量池中”kvill”的引用 
true

 

  • 關於equals()和==:

這個對於String簡單來說就是比較兩字符串的Unicode序列是否相當,如果相等返回true;String類已經重寫過了equals方法。

而==是比較兩字符串的地址是否相同,也就是是否是同一個字符串的引用

而在符合數據類型中,則equals和==都是比較兩對象的地址是否相同,除非重寫equals,詳見hashcode與equals的區別。

  • 使用equals方法比較兩個相同的StringBuffer對象
     StringBuffer sb0=new StringBuffer("hello");
        StringBuffer sb1=new StringBuffer("hello");
        System.out.println(sb0==sb1);
        System.out.println(sb0.equals(sb1));
        System.out.println(sb0.toString().equals(sb1.toString()));
false
false
true

StringBuffer 類沒有重寫Object類下的equals方法,所以實質還是==比較,所以如果需要比較兩個StringBuffer對象是否相等則toString()方法轉為String。

  • .關於String是不可變的 

    這一說又要說很多,大家只要知道String的實例一旦生成就不會再改變了,比如說:String str=”kv”+”ill”+” “+”ans”; 
    就是有4個字符串常量,首先”kv”和”ill”生成了”kvill”存在內存中,然后”kvill”又和” “ 生成 ”kvill “存在內存中,最后又和生成了”kvill ans”;並把這個字符串的地址賦給了str,就是因為String的“不可變”產生了很多臨時變量,這也就是為什么建議用StringBuffer的原 因了,因為StringBuffer是可改變的。
  • 可不可以在分割字符串是使用多個分割符

 

String str="2012-05-25 13:24:16";
        String[] s=str.split("-|:|\\s");
        for(String temp:s){
            System.out.print(temp+" ");
        }
2012 05 25 13 24 16

 

關鍵點就是在split()方法中使用多個分割符;其實split()方法里的分割符參數是一個正則表達式,所以可以使用或操作符(|)鏈接多個分割符,這樣在分割的時候就會按照所有的分割符對字符串進行分割了。\s表示空格,不過在字符串使用過程中還需要在\s之前添加轉義字符"\",否則會出現編譯錯誤。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM