Java數據類型:String

內容:創建String 的方式,String比較方式,String類,實例對象的小區別,一些工具包

首先,查看String源碼:有幾個比較重要的點

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    }

class被final修飾,這意味着String不能被繼承,也不能使用Object instanceof String得到bool;

    private final char value[];

value對應的是String實例出來的具體的值對應的char[],被final修飾,意味着該值不能被修改(但是可以重新給實例對象指向新的地址)

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;
    }

String重寫equlas()equals是在不爲空的情況下比較char的長度,長度相同 再一一比較char

    public String substring(int beginIndex) {
        if (beginIndex < 0) {
            throw new StringIndexOutOfBoundsException(beginIndex);
        }
        int subLen = value.length - beginIndex;
        if (subLen < 0) {
            throw new StringIndexOutOfBoundsException(subLen);
        }
        return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);
    }

String 類下的方法substring 我們可以看到返回的值 是new String的,所以使用substring的時候並不會影響原對象本身。其他的方法也是如此。

在Java中有字符串常量池舉個栗子
下面是對字符串“hello”的幾種聲明方式,發現value都是一樣的。但是用"=="來進行比較的時候,前面三個是true.
最後一個與前面任何一個在棧內地址都不相同。
在這裏插入圖片描述

  • 字符串常量池是爲了減少在JVM中創建的字符串的數量,字符串類維護了一個字符串常量池,該池是Java堆內存中一個特殊的存儲區域。
String str2 = "hell"+"o";
String str3 = "hello";

上面這兩種在JVM字符串常量池中爲什麼不是創建了三個"hell",“o”,"hello"呢,因爲JVM對字符串這個特殊的數據進行了特殊的處理。上面兩種聲明在字符串常量池中申請的是同一個。

  • new String(“hello”);在字符串常量池中與上面幾種申請的其實是同一處地址,但是爲什麼與前面幾種方式的任意一種使用==的時候返回false。雖然在常量池中是同一個值,但是對應對象的"棧"卻是不同的,new關鍵字創建的對象是開闢內存新的地址。
    StringBuffer
    是我們常用的字符串處理的一個類。
 public final class StringBuffer
    extends AbstractStringBuilder
    implements java.io.Serializable, CharSequence
{}

該類也是被final修飾的,意味着不能被繼承。

    @Override
    public synchronized StringBuffer append(String str) {
        toStringCache = null;
        super.append(str);
        return this;
    }

在他的append字符串拼接值的方法是被synchronized 意味着該類在多線程中是線程安全的。

StringBuilder

public final class StringBuilder
    extends AbstractStringBuilder
    implements java.io.Serializable, CharSequence
{}

StringBuilder同樣被final修飾,該類也是不能被繼承的最終。

    @Override
    public StringBuilder append(String str) {
        super.append(str);
        return this;
    }

沒有被鎖鎖着,所以多線程下“寫”不安全。
String對象被傳值

    private static void changesValue(String str){
        str = "hello zhangsan";
    }
    public static void main(String[] args) {
        String lisi = "lisi";
        changesValue(lisi);
        System.out.println(lisi);
        lisi = "hello wangwu";
        System.out.println(lisi);
    }

結果:

lisi
hello wangwu

觀察上面的結果可以發現,String爲不可變類型,在方法內對String修改的時候,相當於傳入的是String的副本,並不是對象本身,所以修改之後也只是修改備份,並不會修改對象本身的值。
但是使用StringBuffer或者StringBuilder的時候是可以進行修改的,因爲StringBuffer下對應的具體的值並沒有被final修飾,在本文的開頭就看到String類下的value是被fianl修飾的。

private transient char[] toStringCache;//StringBuffer
private final char value[];//String

Utils
我常使用的String工具類:

<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.9</version>
</dependency>

裏面有判空,去空格等處理。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章