1. 程式人生 > 實用技巧 >Java基礎之:String類

Java基礎之:String類

Java基礎之:String類

String物件用於儲存字串,也就是一組字元序列

常量物件:字串常量物件是用雙引號括起來的字元序列,例如:"小范",”12.34“,”xiaofan“等

字串的字元使用Unicode字元編碼,一個字元(不區分字母還是漢字)佔兩個位元組。

String物件的兩種建立方式

第一種:String s1 = "xiaofan";

第二種:String s2 = new String("xiaofan");

說明:

方法一是直接賦值,而方法二是呼叫構造器。方法一會直接將引用指向常量池中的”xiaofan“,而方法二會先在堆中建立一個空間,在此空間中放入指向常量池"xiaofan"的地址,再讓棧空間的物件名指向堆地址。

由於這兩種建立方式的不同指向,會出現很多字串比較是否相等上的問題。

簡單案例

package class_string;
​
public class ClassTest {
​
    public static void main(String[] args) {
​
        String s = "hello"; //常量池中建立hello,指向它
        String ss = new String ("hello");   //堆中建立物件,指向常量池中的hello
        System.out.println(s.equals(ss));   //比較內容,T
        System.out.println(s == ss);    //比較地址,F
        
        String a = "abc";
        String b = "abc"; // 因為上面a已經在常量池中建立了abc,所以b直接指向b就可以了
        System.out.println(a.equals(b));    //比較內容,T
        System.out.println(a == b); //比較地址,T
        
        String x = new String("XYZ");   
        String y = new String("XYZ"); //x、y都在堆中建立了物件,但它們的物件都指向常量池中的XYZ
        System.out.println(x.equals(y));    //比較內容,T
        System.out.println(x == y); //比較地址,F
        
        System.out.println("============");
        
        String a1 = "abc"; // a1指向 常量池
        String b1 =new String("abc");//b1 指向堆
        System.out.println(a1.equals(b1)); //T , 比較內容
        System.out.println(a1==b1); // F,比較地址
        System.out.println(a1==b1.intern()); //T , b1.intern() 指向常量池的”abc”
        System.out.println(b1==b1.intern());//F  , 物件b1的堆地址和常量池中"abc"的地址比較
        
        /*  b1.intern() 方法最終返回的是常量池的地址(物件)
         *  當呼叫 intern 方法時,如果池已經包含一個等於此 String 物件的字串
         * (用 equals(Object) 方法確定),則返回池中的字串。
         *  否則,將此 String 物件新增到池中,並返回此 String 物件的引用
         */
        
        System.out.println("============");
        
        class Person{
            private String name;
        }
        
        Person p1 = new Person();
        p1.name = "chuannong"; 
        Person p2 = new Person();
        p2.name = new String("chuannong");
​
        System.out.println(p1.name.equals(p2.name));  //T
        System.out.println(p1.name == p2.name);     //F,p1.name 指向常量池,p2.name 指向堆空間 
        System.out.println(p1.name == "chuannong");   //T
        System.out.println(p1.name.intern());   //返回"chuannong"
    }
}

  

字串的特性

可以從最開始介紹String類的時候看到,它的物件底層是儲存在一個final陣列中的。

所以對於String物件儲存的字串來所,一個字串物件一旦分配,其內容就是不可變的。

package class_string;
/**
 *  String is final
 */
public class ClassTest02 {
    public static void main(String[] args) {
        //在常量池中建立了兩個物件,"abc"、"hello"
        String a = "abc";
        a = "hello";
        
        //在常量池中建立了一個物件,"abchello",可以理解為,abc與hello並沒有被指向引用,所以不需要建立
        String b = "abc" + "hello"; //編譯器會自動的處理"+",將abc 和 hello 拼接起來
        
        //在常量池中建立了三個物件,"xiao"、"fan"、"xiaofan"
        String c = "xiao";  //有c指向"xiao",所以建立
        String d = "fan";   //同理
        String e = c + d ;
        
        /*
         * 因為String物件 底層是放在  private final char value[]; 這裡面的
         * 所以String是final的,若想要進行拼接或更改字串,只能是重新在常量池中建立物件
         */
    }
}

String類使用

瞭解了String物件兩種宣告方式不同,以及字串特性之後。就又會出現一些對於字串宣告上的問題。

簡單案例

package class_string;
​
public class ClassTest03 {
    
    String str = new String("good");
    final char[] ch = { 't', 'e', 's', 't' };
​
    public static void main(String[] args) {
        ClassTest03 ex = new ClassTest03();
        ex.change(ex.str, ex.ch);
        System.out.print(ex.str + " and ");
        System.out.println(ex.ch);
    }
​
    public void change(String str, char ch[]) {
        str = "test";
        ch[0] = 'g';
    }
}

程式輸出:good and gest

案例理解:

  1. 程式載入時,首先在棧空間建立main方法空間,建立ex物件

  2. 在ex物件的堆空間中,建立一個String引用str指向另外一個堆空間,此堆空間中放"good"在常量池中的地址

  3. 在ex物件的堆空間中,建立一個char[]引用ch 指向另外一個堆空間,此堆空間存放 { 't', 'e', 's', 't' }

  4. 在棧空間中建立change方法空間,傳入物件ex的str與ch引用地址

  5. str = "test" ,在常量池中建立"test",返回給str,即將change方法中的str的引用改變,不再指向堆空間的地址,而變為指向常量池中的"test"

  6. ch[0] = 'g' ,將change方法中的ch[0]該為g,即直接改變堆空間中的ch陣列

  7. change方法結束,change方法空間銷燬,此時 main方法空間中的str並沒有改變,ch陣列的第一個改變為g,常量池中多了一個"test"。

String類的常用方法

第一部分:

package class_string;
public class StringMethods {
    public static void main(String[] args) {
        String username = "JOHN";
        // 2.equalsIgnoreCase 忽略大小寫的判斷內容是否相等
        if ("john".equalsIgnoreCase(username)) {
            System.out.println("Success!");
        } else {
            System.out.println("Failure!");
        }
        // 3.length 獲取字元的個數,字串的長度
        System.out.println("小范".length());  //輸出:2
        // 4.indexOf 獲取字元在字串物件中第一次出現的索引,索引從0開始,如果找不到,返回-1
        String s1 = "wer@terwe@g";
        int index = s1.indexOf('@');
        System.out.println(index);//輸出:3
        // 5.lastIndexOf 獲取字元子啊字串中最後一次出現的索引,索引從0開始,如果找不到,返回-1
        String s2 = "wer@terwe@g@";
        int index2 = s1.lastIndexOf('@');
        System.out.println(index);//輸出:3
        // 6.substring 擷取指定範圍的子串
        String name = "hello,小范";
        System.out.println(name.substring(6));// 擷取後面的字元,輸出:小范
        System.out.println(name.substring(0, 5));//輸出:hello
    }
}

  

第二部分:

package class_string;
​
public class StringMethods02 {
​
    public static void main(String[] args) {
        // 1.toUpperCase轉換成大寫
        String s = "heLLo";
        System.out.println(s.toUpperCase());
        // 2.toLowerCase
        System.out.println(s.toLowerCase());
        // 3.concat拼接字串
        String s1 = "小范";
        s1 = s1.concat("小黃").concat("小雨").concat("together");
        System.out.println(s1);
        // 4.replace 替換字串中的字元
        String s2 = "小范 and 小黃 小黃 小黃 小黃";
        s2 = s2.replace("小黃", "小雨");
        System.out.println(s2);
        // 5.split 分割字串, 對於某些分割字元,我們需要 轉義比如 | \\等
        System.out.println("======================");
        String poem = "鵝鵝鵝,曲項向天歌,白毛浮綠水,紅掌撥清波";
        String[] split = poem.split(",");
        for (int i = 0; i < split.length; i++) {
            System.out.println(split[i]);
        }
        System.out.println("======================");
        String poem2 = "E:\\附加專案\\附加-project";
        String[] split3 = poem2.split("\\\\");
        for (int i = 0; i < split3.length; i++) {
            System.out.println(split3[i]);
        }
        // 6.toCharArray 轉換成字元陣列
        System.out.println("======================");
        String s4 = "happy";
        char[] chs = s4.toCharArray();
        for (int i = 0; i < chs.length; i++) {
            System.out.println(chs[i]);
        }
        // 7.compareTo 比較兩個字串的大小,如果前者大,則返回正數,後者大,則返回負數,如果相等,返回0
        System.out.println("======================");
        String a = "jchn";
        String b = "jack";
        System.out.println(a.compareTo(b)); // 返回值是 'c' - 'a' = 2的值
        System.out.println("a".compareTo("d")); // 返回值是 'a' - 'd' = -3的值
        System.out.println("a".compareTo("a")); // 返回值是 'a' - 'a' = 0的值
​
        // 8.format 格式字串
        /*
         * 佔位符有: %s 字串 %c 字元 %d 整型 %.2f 浮點型
         * 
         */
        System.out.println("======================");
        String name = "john";
        int age = 10;
        double score = 98.3 / 3;
        char gender = '男';
        // String info =
        // "我的姓名是"+name+"年齡是"+age+",成績是"+score+"性別是"+gender+"。希望大家喜歡我!";
        String info = String.format("我的姓名是%s年齡是%d,成績是%.2f性別是%c.希望大家喜歡我!", name, age, score, gender);
        System.out.println(info);
    }
}

程式輸出:

HELLO

hello

小范小黃小雨together

小范 and 小雨 小雨 小雨 小雨

========================

鵝鵝鵝

曲項向天歌

白毛浮綠水

紅掌撥清波

========================

E:

附加專案

附加-project

========================

h a p p y

========================

2 -3 0

========================

我的姓名是john年齡是10,成績是32.77性別是男.希望大家喜歡我!

簡單應用案例

package class_string;
​
import java.util.Scanner;
​
/**
 *   判斷郵箱是否合法,要求裡面必須包含@和.    而且 @ 必須在. 的前面
    案例:不使用系統提供的trim 方法,自己寫一個myTrim方法,去除字串兩端的空格,
    比如 "     hello world   "  => 返回 “hello world”
 */
public class ClassWork01 {
​
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("請輸入郵箱:");
        String email =  scanner.next();
        if(legalEmail(myTrim(email))) {
            System.out.println("輸入正確,你的Email地址為:" + email);
        }else {
            System.out.println("輸入錯誤!");
        }
    }
    
    public static String myTrim(String email) {
        String temp = "";
        for(int i = 0;i<email.length();i++) {   //去除前面的空格
            if(email.charAt(i) != ' ') {
                temp = email.substring(i);
                break;
            }
        }
        
        for(int i = temp.length() - 1;i >= 0;i--) { //去除後面的空格
            if(temp.charAt(i) != ' ') {
                email = temp.substring(0,i);
                break;
            }
        }
        return email;
    }
    
    public static boolean legalEmail(String email) {
        
        if(email.indexOf("@") < 0 && email.indexOf(".") < 0) {  //沒有@和.
            return false;
        }else {
            if(email.indexOf("@") != email.lastIndexOf("@")) {  //不止一個@
                return false;
            }else {
                if(email.indexOf("@") > email.indexOf(".")) {   //"."不在@之後
                    return false;
                }
            }
        }
        return true;
    }
}