1. 程式人生 > >java中三個特殊的類------String類、Object類、包裝類

java中三個特殊的類------String類、Object類、包裝類

1.String類

1.1 String類的兩種例項化方式

  1. 直接賦值
    String str = "hello"
  2. 通過構造方法例項化String類
    String str = new String("hello")

1.2 字串相等比較(內容)
public boolean equals(String anotherString);成員方法,需要通過物件呼叫
例:
str1.equals(str2);
看程式碼:

public class Test{
    public static void main(String[] args){
        String str1 = "hello";
        String str2 = new String("hello");
        System.out.println(str1 == str2);
        System.out.println(str1.equals(str2));
    }
}

輸出結果:
false
true
這裡就體現出equals()方法的作用了,str1 == str2這判斷的是這兩個字串的地址是否相同,因為str2用了new,重新開闢了一個新空間,所以和str1的地址肯定是不相同的;但equals()比較的是兩個字串的內容,str1和str2內容相同,所以返回true。
看圖:
在這裡插入圖片描述

1.3字串常量是String的匿名物件
例:"hello".equals(str2);
這裡有一個坑,如果我們使用:str.equals(“hello”),有可能會出現nullPointException(空指標異常)報錯,因為str可能是一個空字串。
所以記住,以後在開發中,如果要判斷使用者輸入的字串是否等同於特定字串,一定要將字串(String常量)寫在前面。
1.4 物件池(物件陣列)


我們先來看一段程式碼吧:

public class Test{
    public static void main(String[] args){
        String str1 = "hello";
        String str2 = "hello";
        System.out.println(str1 == str2);
    }
}

我們先來猜猜這個的返回值吧。肯定好多人都認為它返回的是false吧,但不是的,為了讓你們相信,直接上圖吧。
在這裡插入圖片描述
沒錯,它返回的就算true。
肯定有疑問了吧,上邊不是說了str1 == str2比較的是地址嗎?它兩地址怎麼會相等。
那是因為JVM底層會自動維護一個字串的物件池,如果採用直接賦值

的形式進行String的物件例項化 (這裡要特別注意,如果使用了new,str1 == str2 )肯定是false,因為new就會開闢一個新空間,地址肯定不相等,這個物件會自動儲存在這個物件池中。如果下次繼續使用直接賦值的形式宣告String類,這個時候,如果物件池中已經有了第二次宣告的這個內容,則會直接引用,不會建立新的空間(所以str1的地址等於str2的地址);如果沒有,則開闢新的堆空間後,再將其儲存在物件池中供下次使用。
再畫圖解釋一下吧:
在這裡插入圖片描述
1.5 字串常量不可變更
字串一旦定義後不可改變。因為字串的底層實現就算字元陣列,我們都知道,陣列最大的一個缺陷就算它的長度是固定的,所以定義字串的常量時,它的內容不可改變。
我們來看看這段程式碼:

public class Test{
    public static void main(String[] args){
        String str = "hello";
        System.out.println(str+"world");
    }
}

它的輸出結果如下:
在這裡插入圖片描述
我們發現hello和world連線在了一起,不是說字串內容一旦定義就不能改變嗎?
其實這裡並沒有改變字串內容,變的是字串物件。我們來看實際的過程圖;
在這裡插入圖片描述
說這個的目的何在呢?
因為改變的是物件的引用,前邊的“hello”和"world"都成了垃圾空間,如果一直+下去,垃圾空間將會特別大。
1.6 字元與字元陣列的相互轉換
a. 將字元陣列轉為字串

public String(char[] value)

public String (char[] value, int offest, int count)//offest表示從陣列的哪個位置開始,count表示將count個字元轉為字串

例:

public class Test{
    public static void main(String[] args){
        char[] arr = {'h','e','l','l','o','w','o','r','l','d'};
        String str1 = new String(arr);
        String str2 = new String(arr, 5, 5);
        System.out.println(str1);
        System.out.println(str2);
    }
}

在這裡插入圖片描述
b. 將字串轉為單個字元

public char charAt(int index)

例:

public class Test{
    public static void main(String[] args){
        String str = "hello world";
        char c = str.charAt(4);
        System.out.println(c);
    }
}

在這裡插入圖片描述
c. 將字串變為字元陣列

public char[] toCharArray()

例:

public class Test{
    public static void main(String[] args){
        String str = "hello world";
        char[] arr = str.toCharArray();
        System.out.println(arr.length);
    }
}

在這裡插入圖片描述
1.7 位元組(byte)與字串
a. 將位元組陣列轉為字串

public String(byte[] value)

public String(byte[] value, int offest, int count)

b.將字串轉為位元組陣列

public byte[] getBytes()

例:

public class Test{
    public static void main(String[] args){
        String str = "hello world";
        byte[] data = str.getBytes();
        for(int i = 0; i < data.length; i++){
            System.out.print(data[i]+"、");
        }
        System.out.println();
        //將位元組陣列轉換為字串
        System.out.println(new String(data));
    }
}

在這裡插入圖片描述
1.8 字串比較
a. 不區分大小寫相等比較

public boolean equalsIgnoreCase(String anotherString)

例:

public class Test{
    public static void main(String[] args){
        String str1 = "hello world";
        String str2 = "Hello World";
        System.out.println(str1.equalsIgnoreCase(str2));
    }
}

在這裡插入圖片描述
b. 比較兩個字串大小

public int compareTo(String anotherString)
  1. 返回大於0:表示大於比較物件
  2. 返回等於0:表示兩者相等
  3. 返回小於0:表示小於比較物件

例:

public class Test{
    public static void main(String[] args){
        String str1 = "hello world";
        String str2 = "Hello World";
        System.out.println(str1.compareTo(str2));
    }
}

在這裡插入圖片描述
1.9 字串查詢

  1. public boolean contains(String str):判斷str在本字串中是否存在
    例:
public class Test{
    public static void main(String[] args){
        String str = "hello world";
        System.out.println(str.contains("ld"));
    }
}

在這裡插入圖片描述
2.public boolean startsWith(String str):判斷是否以指定字串開頭
例:

public class Test{
    public static void main(String[] args){
        String str = "hello world";
        System.out.println(str.startsWith("e"));
    }
}

在這裡插入圖片描述
3. public boolean startsWith(String str, int index):判斷指定位置是否以指定字串開頭
例:

public class Test{
    public static void main(String[] args){
        String str = "hello world";
        System.out.println(str.startsWith("w", 6));
    }
}

在這裡插入圖片描述
4. public boolean endsWith(String str):判斷是否以指定字串結尾
例:

public class Test{
    public static void main(String[] args){
        String str = "hello world";
        System.out.println(str.endsWith("d"));
    }
}

在這裡插入圖片描述
1.10 字串替換

  1. public String replaceAll(String regex, String replacement):替換所有指定內容
    例:
public class Test{
    public static void main(String[] args){
        String str = "hello world";
        System.out.println(str.replaceAll("l", "_"));
    }
}

在這裡插入圖片描述
2. public String replaceFirst(String regex, String replacement):替換首個指定內容
例:

public class Test{
    public static void main(String[] args){
        String str = "hello world";
        System.out.println(str.replaceFirst("l", "_"));
    }
}

在這裡插入圖片描述
1.11 字串拆分
3. public String[] split(String regex):將字串按照指定格式全部拆分
例:

public class Test{
    public static void main(String[] args){
        String str = "hello world";
        String[] result = str.split(" ");//按照空格拆分
        for(String s: result){
            System.out.println(s);
        }
    }
}

在這裡插入圖片描述
4. public String[] split(String regex, int limit):將字串按照指定格式部分拆分,陣列長度為limit
例:

public class Test{
    public static void main(String[] args){
        String str = "hello world haha";
        String[] result = str.split(" ", 2);
        for(String s: result){
            System.out.println(s);
        }
    }
}

在這裡插入圖片描述
1.12 字串擷取
5. public String substring(int beginIndex):從指定位置開始擷取到字串結尾
例:

public class Test{
    public static void main(String[] args){
        String str = "hello world haha";
        System.out.println(str.substring(3));
    }
}

在這裡插入圖片描述
6. public String substring(int beginIndex, int endIndex):擷取部分
例:

public class Test{
    public static void main(String[] args){
        String str = "hello world haha";
        System.out.println(str.substring(3, 9));
    }
}

在這裡插入圖片描述
1.13 String類的其他方法
a. 去掉左右空格

public String trim()

例:

public class Test{
    public static void main(String[] args){
        String str = "   hello world haha ";
        System.out.println(str.trim());
    }
}

在這裡插入圖片描述
b. 字串轉大小寫

public String toUpperCase()

public String toLowerCase()

例:

public class Test{
    public static void main(String[] args){
        String str = "hello world";
        String str1 = "HELLO";
        System.out.println(str.toUpperCase());
        System.out.println(str1.toLowerCase());
    }
}

在這裡插入圖片描述
c. 判斷字串是否為空(只能判斷是否為空字串而不是null)

public boolean isEmpty()

例:


public class Test{
    public static void main(String[] args){
        String str = "";
        System.out.println(str.isEmpty());
    }
}

在這裡插入圖片描述
在這裡插入圖片描述
1.14 兩隻sb(StringBuffer()、StringBuilder())----方便字串的修改(前邊說過String是不能修改字串的)
a. 字串修改

public StringBuffer append(各種資料型別)

例:

public class Test{
    public static void main(String[] args){
        StringBuffer sb = new StringBuffer();
        sb.append("hello").append("world");
        fun(sb);
        System.out.println(sb);
    }
    public static void fun(StringBuffer s){
        s.append("\n").append("Calm");
    }
}

在這裡插入圖片描述
b. StringBuffer與String的相互轉換
(1)String轉成StringBuffer
呼叫StringBuffer的構造方法或append()方法
(2)StringBuffer轉為String
呼叫toStrig()方法
c. 字串反轉

public StringBuffer reverse()

例:

public class Test{
    public static void main(String[] args){
        StringBuffer sb = new StringBuffer();
        sb.append("hello").append("world");
        System.out.println(sb.reverse());
    }
}

在這裡插入圖片描述
d. 刪除指定範圍的資料

public StringBuffer delete(int start, int end)

例:

public class Test{
    public static void main(String[] args){
        StringBuffer sb = new StringBuffer();
        sb.append("hello").append("world");
        System.out.println(sb.delete(2, 5));
    }
}

在這裡插入圖片描述
e. 插入資料

public StringBuffer insert(int offest, 各種資料型別)

例:

public class Test{
    public static void main(String[] args){
        StringBuffer sb = new StringBuffer();
        sb.append("hello").append("world");
        System.out.println(sb.insert(2, "你好"));
    }
}

在這裡插入圖片描述
總結
String、StringBuffer、StringBuilder的區別:

  1. String的內容不可以修改,而兩隻sb可修改內容(append)
  2. StringBuffer採用同步處理,執行緒安全,效率較低
  3. StringBuilder採用非同步處理,執行緒不安全,效率較高。
    例:
		String s = "hello";
        System.out.println(s+"world");

底層會將String自動轉換為StringBuilder。

2.Object類-----接收除基本型別所有的類的物件

Object是java預設提供的類

java中,除了Object類,所有的類都存在繼承關係,預設會繼承Object父類,所有類(除了8大基本型別(byte、short、int、long、float、double、char、boolean))物件都可以通過Object類進行接收。

2.1 取得物件資訊-----toString()
直接使用物件的輸出,預設輸出一個地址編碼,但如果輸出的是String物件,此時會輸出字串的內容而不是地址,這是因為String覆寫了Object的toString()方法。

System.out.println():系統輸出預設會呼叫物件的toString(),也就算說,一旦出現System.out.println(),其實就算呼叫了toString(),輸出的是toString()裡的東西。

例:

class Person{
    private int age;
    private String name;

    public Person(int age, String name) {
        this.age = age;
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {

        return age;
    }

    public String getName() {
        return name;
    }
}
public class Test{
    public static void main(String[] args){
        Person person = new Person(18,"張三");
        System.out.println(person);
    }
}

在這裡插入圖片描述
從輸出結果可以看出,輸出的是一個地址編碼,這個地址就算Person類的地址。
現在我們想要輸出年齡和姓名的話,就需要覆寫它的toString()方法。
看程式碼:

class Person{
    private int age;
    private String name;

    public Person(int age, String name) {
        this.age = age;
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {

        return age;
    }

    public String getName() {
        return name;
    }

    @Override
    public String toString() {
        return "Person{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}
public class Test{
    public static void main(String[] args){
        Person person = new Person(18,"張三");
        System.out.println(person);
    }
}

我們現在再來看看輸出結果:
在這裡插入圖片描述

如果我們不想輸出地址,而要輸出本類資訊,就需要在子類中覆寫toString()方法。

2.2 物件比較-----equals()
String類物件的比較使用的是equals()方法,實際上,String類的equals()也是覆寫了Object類的equals()方法。
例:

class Person{
    private int age;
    private String name;

    public Person(int age, String name) {
        this.age = age;
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {

        return age;
    }

    public String getName() {
        return name;
    }

    @Override
    public String toString() {
        return "Person{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }

    @Override
    public boolean equals(Object obj){
        if(obj == null){
            return false;
        }
        if(this == obj){
            return true;
        }
        //如果obj不是Person類物件
        if(!(obj instanceof Person)){
            return false;
        }
        //向下轉型,比較屬性值
        Person per = (Person) obj;
        return (this.age == per.age) && (this.name.equals(per.name));
    }
}
public class Test{
    public static void main(String[] args){
        Person person1 = new Person(18,"張三");
        Person person2 = new Person(18,"張三");
        System.out.println(person1.equals(person2));
    }
}

在這裡插入圖片描述
2.3 接收引用資料型別
Object可以接收所有引用型別,包括:類、陣列、介面。

public class Test{
    public static void main(String[] args){
        //Object接收陣列物件,發生向上轉型
        Object obj = new int[]{1, 4, 2, 7};
        //向下轉型,需要強轉
        int[] data = (int[]) obj;
        for(int i : data){
            System.out.print(i+"、");
        }
    }
}

在這裡插入圖片描述

3. 包裝類

包裝類就算將基本型別封裝到類中。

自己實現一個包裝類:

class IntDemo{
    private int num;
    public IntDemo(int num){
        this.num = num;
    }
    public int intValue(){
        return this.num;
    }
}
public class Test{
    public static void main(String[] args){
        //子類物件向上轉型
        Object obj = new IntDemo(78);
        //向下轉型
        IntDemo data = (IntDemo) obj;
        //取出裡面的基本資料型別操作
        System.out.println(data.intValue());
    }
}

在這裡插入圖片描述
IntDemo實際上就算int型別的包裝類,使用intValue()就可以實現將基本型別變為物件的需求。

3.1 分類
a. 物件型包裝類(Object的直接子類):Boolean(boolean)、Character(char)
b. 數值型包裝類(Number的直接子類),存在數值轉換異常:Byte(byte)、Integer(int)、Short(short)、Long(long)、Double(double)、Float(float)
3.2 裝箱與拆箱-----基本資料型別與相應包裝類的資料處理

裝箱:將基本資料型別變為包裝類物件,利用每個包裝類提供的構造方法實現包裝。

Integer num = new Integer(19);

拆箱:將包裝類中包裝的基本型別值取出來,利用Number類提供的xxValue()方法實現拆箱處理。

int data = num.intValue();

在JDK1.5之後提供了自動拆裝箱處理機制。

//自動裝箱
Integer num = 34;
//自動拆箱
System.out.println(--num * 2);

包裝類物件之間的值比較依然要使用equals()方法
我們下來看一段程式碼,就知道為什麼要這樣了。

public class Test{
    public static void main(String[] args){
        Integer num1 = new Integer(20);
        Integer num2 = new Integer(20);
        System.out.println(num1 == num2);
        System.out.println(num1 == new Integer(20));
        System.out.println(num1.equals(new Integer(20)));
    }
}

在這裡插入圖片描述
至於原因,在上邊String類裡已經解釋的很清楚了。這裡有兩個new,沒new一次就會在堆空間裡開闢一個新空間,所以num1和num2的地址不同。

public class Test{
    public static void main(String[] args){
        Integer num1 = new Integer(20);
        Integer num2 = 20;
        Integer num3 = 200;
        Integer num4 = 200;
        Integer num5 = 56;
        Integer num6 = 56;
        System.out.println(num1 == num2);
        System.out.println(num3 == num4);
        System.out.println(num5 == num6);
    }
}

在這裡插入圖片描述
為什麼會出現上邊這種現象呢?
那是因為對於Integer來說,如果它的物件值在-128~127之間的直接賦值,Integer物件在Integer常量池產生,會複用已有物件,這個區間內的Integer值可以直接使用==判斷。除此之外,所有的資料都會在堆上產生,並不會複用已有物件。

3.3 字串與基本型別的轉換

  1. 將字串轉為基本型別(靜態方法)
    呼叫各個包裝類.parsexx(String str)
    例:
public class Test{
    public static void main(String[] args){
        String str = "123";
        System.out.println(Integer.parseInt(str));
    }
}

在這裡插入圖片描述
但如果123後邊還有字串型別的字元的話,轉換就會出錯:
在這裡插入圖片描述
2. 基本型別變為字串
a. “”+基本型別,會產生垃圾空間
b. 使用Sting類的valueOf(基本型別),此方法不會產生垃圾空間

public class Test{
    public static void main(String[] args){
        int num = 100;
        String str = String.valueOf(num);
        System.out.println(str.length());
    }
}

在這裡插入圖片描述