国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

目次
String公式紹介
英語版
定義タイプ" > 定義タイプ
日常の開発では、特に次のような場合に文字列が使用される場所が多すぎます。変數(shù)と定數(shù)の型を定義するには、基本的にコードを記述している限り、いつでもそれを確認できます。
String クラスには 20 を超えるメソッドがあり、使用例を以下に示します (ほとんどのメソッドはここでデモされており、殘りは自分で試すことができます)。
String核心部分源碼分析 " >String核心部分源碼分析
String類源碼注釋
String類定義
重要成員
構(gòu)造方法
常用方法分析
hashCode方法
equals()方法
substring()方法
intern()方法
length()方法
isEmpty() 方法
charAt(int index) 方法
getBytes()方法
compareTo()方法
startsWith()方法
concat()方法
replace()方法
trim()方法
valueOf()方法
split() 方法
String在面試中常見問題 " >String在面試中常見問題
如何比較字符串相同?
String str=new String("abc");這行代碼創(chuàng)建了幾個對象?
String と StringBuilder および StringBuffer の違い
String 和 JVM有什么關(guān)系?
如何判斷兩個字符串中含有幾個相同字符
String有沒有長度限制?是多少?為什么?
字符串對象能否用在switch表達式中?
說說String中intern方法
好了,關(guān)于Stirng類的分享就到此,歡迎找我探討更多技術(shù)問題。
ホームページ Java &#&チュートリアル 2wワード詳細説明文字列、yyds

2wワード詳細説明文字列、yyds

Aug 24, 2023 pm 03:56 PM
string


まえがき

みなさん、こんにちは。今日は、 Java String の基本。

String クラスの重要性は言うまでもありませんが、バックエンド開発で最もよく使われるクラスとも言えるので、必ず説明しておきます。

この記事の主な內(nèi)容は次のとおりです。

2wワード詳細説明文字列、yyds


##文字列の紹介

まず Java の 8 つの主要なデータ型について説明し、次に String について説明します。

8 つの基本データ型

バイト: 8 ビット、格納されるデータの最大量は 255、格納されるデータの範囲は -128 ~ 127 です。

short: 16 ビット、最大データ記憶容量は 65536、データ範囲は -32768 ~ 32767 です。

int: 32 ビット、最大データ記憶容量は 2 の 32 乗マイナス 1、データ範囲は負の 2 の 31 乗から正の 2 の 31 乗マイナス 1 までです。

long: 64 ビット、最大データ記憶容量は 2 の 64 乗マイナス 1、データ範囲は負の 2 の 63 乗から正の 2 の 63 乗マイナス 1 までです。

float: 32 ビット、データ範囲は 3.4e-45 ~ 1.4e38 直接代入する場合は數(shù)値の後に f または F を付ける必要があります。

double: 64 ビット、データ範囲は 4.9e-324 ~ 1.8e308、値を割り當てるときに d または D を追加することも追加しないこともできます。

ブール値: 値は true と false の 2 つだけです。

char: 16 ビット、Unicode コードを格納し、一重引用符で値を割り當てます。

これら 8 つの主要なデータ型 (ご存知だと思いますが、8 つの主要なデータ型には対応するカプセル化タイプもあります) に加えて、Java には特別な型もあります。String (文字通り文字列を意味します)。

String公式紹介

英語版

2wワード詳細説明文字列、yyds


##アドレス:
https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/String.html

理解できませんか?ブラウザに付屬の翻訳ツールを借りますので、元の英語が理解できれば幸いです。

String は、インストールした

JDK

ディレクトリの下の rt.ar パッケージに存在します。完全パス名は、java.lang.String です。 。 String は、Java コードで文字列を表すために使用されます。次に例を示します。 <pre class='brush:php;toolbar:false;'>String str = &quot;中國夢,我的夢&quot;; String name = &quot;zhangsan&quot;;</pre> とりあえず、これだけは知っておいてください。

文字列の使用法

定義タイプ

日常の開発では、特に次のような場合に文字列が使用される場所が多すぎます。変數(shù)と定數(shù)の型を定義するには、基本的にコードを記述している限り、いつでもそれを確認できます。

例: ユーザー情報は、エンティティ クラス User によって表されます。

public class User{
    private Long id;
    private String userName;
    private String address;
    private String password;
    ....
}

一般的なメソッドのデモ

String クラスには 20 を超えるメソッドがあり、使用例を以下に示します (ほとんどのメソッドはここでデモされており、殘りは自分で試すことができます)。

//案例代碼,來源于網(wǎng)絡(luò)
public class StringDemo {
    public static void main(String[] args) throws Exception {
        String str1 = "Hello World";
        String str2 = "Hello World";
        String str3 = "hello world";
        String str4 = " hello world ";
        //返回字符串的長度
        System.out.println("r1: " + str1.length());
        //比較兩個字符串的大小compareTo(返回的是int),0相等,復(fù)數(shù)小于,正數(shù)大于
        System.out.println("r2 : " + str1.compareTo(str2));
        //比較兩個字符串的大小compareTo(返回的是int),0相等,復(fù)數(shù)小于,正數(shù)大于
        System.out.println("r3 : " + str1.compareTo(str3));
        //字符串比較compareToIgnoreCase,忽略大小寫。0相等,復(fù)數(shù)小于,正數(shù)大于
        System.out.println("r4 : " + str1.compareToIgnoreCase(str3));
        //字符串查找indexOf,返回的是找到的第一個的位置,沒找到返回-1。從0開始
        System.out.println("r5 : " + str1.indexOf("o"));
        //查找字符串最后一次出現(xiàn)的位置lastIndexOf
        System.out.println("r6 : " + str1.lastIndexOf("o"));
        //刪除字符串中的一個字符,字符串從0開始的 substring(a, b)
        //返回指定起始位置(含)到結(jié)束位置(不含)之間的字符串
        System.out.println("r7 : " + str1.substring(0, 5) + str1.substring(6));

        //字符串替換,替換所有
        System.out.println("r8 : " + str1.replace("o", "h"));
        //字符串替換,替換所有
        System.out.println("r9 : " + str1.replaceAll("o", "h"));
        //字符串替換,替換第一個
        System.out.println("r10 : " + str1.replaceFirst("o", "h"));
        //字符串反轉(zhuǎn)
        System.out.println("r11 : " + new StringBuffer(str1).reverse());
        //字符串反轉(zhuǎn)
        System.out.println("r11’: " + new StringBuilder(str1).reverse());
        //字符串分割
        String[] temp = str1.split("\\ ");
        for (String str : temp) {
            System.out.println("r12 : " + str);
        }
        //字符串轉(zhuǎn)大寫
        System.out.println("r13 : " + str1.toUpperCase());
        //字符串轉(zhuǎn)小寫
        System.out.println("r14 : " + str1.toLowerCase());
        //去掉首尾空格
        System.out.println("r15 : " + str4.trim());
        //是否包含,大小寫區(qū)分
        System.out.println("r16 : " + str1.contains("World"));
        //返回指定位置字符
        System.out.println("r17 : " + str1.charAt(4));
        //測試此字符串是否以指定的后綴結(jié)束
        System.out.println("r18 : " + str1.endsWith("d"));
        //測試此字符串是否以指定的前綴開始
        System.out.println("r19 : " + str1.startsWith("H"));
        //測試此字符串從指定索引開始的子字符串是否以指定前綴開始
        System.out.println("r20 : " + str1.startsWith("ll", 2));
        //將指定字符串連接到此字符串的結(jié)尾。等價于用“+”
        System.out.println("r21 : " + str1.concat("haha"));
        //比較字符串的內(nèi)容是否相同
        System.out.println("r22 : " + str1.equals(str2));
        //與equals方法類似,忽略大小寫
        System.out.println("r23 : " + str1.equalsIgnoreCase(str2));
        //判斷是否是空字符串
        System.out.println("r24:  " + str1.isEmpty());

    }
}

我們開發(fā)中差不多也就是這么使用了,但是如果你僅僅是使用很牛了,貌似遇到面試照樣會掛。所以,學知識,不能停留在使用層面,需要更深層次的學習。

下面我們就來深層次的學習String,希望大家?guī)е活w平常的心學習,不要害怕什么,燈籠是張紙,捅破不值錢。

String核心部分源碼分析

備注:JDK版本為1.8+,因為JDK9版本中和舊版本有細微差別。

String類源碼注釋

/**
 * The {@code String} class represents character strings. All
 * string literals in Java programs, such as {@code "abc"}, are
 * implemented as instances of this class.
 * 這個String類代表字符串。java編程中的所有字符串常量。
 * 比如說:"abc"就是這個String類的實例
 * <p>
 * Strings are constant; their values cannot be changed after they
 * are created. 
 * 字符串是常量,他們一旦被創(chuàng)建后,他們的值是不能被修改。(重點)
 * String buffers support mutable strings.
 * String緩存池支持可變的字符串,
 * Because String objects are immutable they can be shared. For example:
 * 因為String字符串不可變,但他們可以被共享。比如:
 * <blockquote><pre class="brush:php;toolbar:false">
 *     String str = "abc";
 * 

* is equivalent to: *

 *     char data[] = {&#39;a&#39;, &#39;b&#39;, &#39;c&#39;};
 *     String str = new String(data);
 * 

* Here are some more examples of how strings can be used: * String使用案例 * System.out.println("abc"); * String cde = "cde"; * System.out.println("abc" + cde); * String c = "abc".substring(2,3); * String d = cde.substring(1, 2); *

* The class {@code String} includes methods for examining * individual characters of the sequence, for comparing strings, for * searching strings, for extracting substrings, and for creating a * copy of a string with all characters translated to uppercase or to * lowercase. Case mapping is based on the Unicode Standard version * specified by the {@link java.lang.Character Character} class. * 這個String類包含了一些測評單個字符序列的方法,比如字符串比較,查找字符串, * 提取字符串,和拷貝一個字符串的大小寫副本。 * 大小寫映射的是基于Character類支持的Unicode的字符集標準版本。 *

* The Java language provides special support for the string * concatenation operator ( + ), and for conversion of * other objects to strings. * java語言提供了對字符串的特殊支持,如:可以通過"+"號來進行字符串的拼接操作, * 為其他類提供了與字符串轉(zhuǎn)換的操作 * String concatenation is implemented * through the {@code StringBuilder}(or {@code StringBuffer}) * class and its {@code append} method. * 字符串的+號拼接操作是通過StringBuilder或者StringBuffer類的append()方法 * 來實現(xiàn)的 * String conversions are implemented through the method * {@code toString}, defined by {@code Object} and * inherited by all classes in Java. * 對象與字符串的轉(zhuǎn)換操作是通過所有類的父類Object中定義的toString()方法來實現(xiàn)的 * For additional information on * string concatenation and conversion, see Gosling, Joy, and Steele, * The Java Language Specification. * *

Unless otherwise noted, passing a null argument to a constructor * or method in this class will cause a {@link NullPointerException} to be * thrown. * 除非有特殊說明,否則傳一個null給String的構(gòu)造方法或者put方法,會報空指針異常的 *

A {@code String} represents a string in the UTF-16 format * in which supplementary characters are represented by surrogate * pairs (see the section Unicode * Character Representations in the {@code Character} class for * more information). * 一個String 對象代表了一個UTF-16編碼語法組成的字符串 * Index values refer to {@code char} code units, so a supplementary * character uses two positions in a {@code String}. *

The {@code String} class provides methods for dealing with * Unicode code points (i.e., characters), in addition to those for * dealing with Unicode code units (i.e., {@code char} values). * 索引值指向字符碼單元,所以一個字符在一個字符串中使用兩個位置, * String 類提供了一些方法區(qū)處理單個Unicode編碼,除了那些處理Unicode代碼單元。 * @since JDK1.0 */

以上便是String類注釋的整個片段,后面剩下的就是作者、相關(guān)類、相關(guān)方法以及從JDK哪個版本開始有的。

String類定義

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

類圖

2wワード詳細説明文字列、yyds


String類被final修飾,表示String不可以被繼承。下面我們來說說String實現(xiàn)三個接口有什么用處:

  • 實現(xiàn)Serializable,可以被序列化
  • 實現(xiàn)Comparable,可以用于比較大?。ò错樞虮容^單個字符的ASCII碼)
  • 實現(xiàn)CharSequence,表示是一個有序字符的序列,(因為String的本質(zhì)是一個char類型數(shù)組)

簡單介紹final

修飾類:類不可被繼承,也就是說,String類不可被繼承了

修飾方法:把方法鎖定,以訪任何繼承類修改它的涵義

修飾遍歷:初始化后不可更改

重要成員

 /** The value is used for character storage. */
// 來用存儲String內(nèi)容的
private final char value[];
// 存儲字符串哈希值,默認值為0
private int hash; // Default to 0
// 實現(xiàn)序列化的標識
private static final long serialVersionUID = -6849794470754667710L;

char value[]被final修飾,說明value[]數(shù)組是不可變的。

構(gòu)造方法

/**
 * Initializes a newly created {@code String} object so that it represents
 * an empty character sequence.  Note that use of this constructor is
 * unnecessary since Strings are immutable.
 * 初始化新創(chuàng)建的String對象,時期表示空字符串序列。
 * 注意:這個構(gòu)造方法的用法是沒必要的,因為字符串是不可變的
 */
public String() {
        this.value = "".value;
}

無參構(gòu)造方法中是將一個空字符串的value值賦給當前value。

 /**
  * Initializes a newly created {@code String} object so that it represents
  * the same sequence of characters as the argument; in other words, the
  * newly created string is a copy of the argument string. Unless an
  * explicit copy of {@code original} is needed, use of this constructor is
  * unnecessary since Strings are immutable.
  * 初始化創(chuàng)建的String對象,時期表示與參數(shù)相同的字符串序列。
  * 換句話說:新創(chuàng)建的字符串是參數(shù)自粗糙的副本。
  * 除非,如果需要original的顯示副本,否則也是沒有必要使用此構(gòu)造方法的
  * 因為字符串是不可變的
  * @param  original
  *         A {@code String}
  */
 public String(String original) {
     this.value = original.value;
     this.hash = original.hash;
 }
//案例:  String str=new String("abc");

把original的value賦給當前的value,并把original的hash賦給當前的hash。

/**
 * Allocates a new {@code String} so that it represents the sequence of
 * characters currently contained in the character array argument. The
 * contents of the character array are copied; subsequent modification of
 * the character array does not affect the newly created string.
 * 分配一個新的{@code String},以便它表示字符數(shù)組參數(shù)中當前包含的字符。這個
 * 復(fù)制字符數(shù)組的內(nèi)容;隨后修改字符數(shù)組不影響新創(chuàng)建的字符串。
 * @param  value
 *         The initial value of the string
 */
public String(char value[]) {
    //注:將傳過來的char數(shù)組copy到value數(shù)組里
    this.value = Arrays.copyOf(value, value.length);
}
//Arrays類中的copyOf方法
public static char[] copyOf(char[] original, int newLength) {
    //創(chuàng)建一個新的char數(shù)組
    char[] copy = new char[newLength];
    //把original數(shù)組中內(nèi)容拷貝到新建的char數(shù)組中
    System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength));
    //返回新建的char數(shù)組
    return copy;
}

使用Arrays類的copyOf方法,新建一個char數(shù)組,將original的內(nèi)容放到新建的char數(shù)組中。

然后,把新建的char數(shù)組賦給當前的vlaue。

public String(StringBuffer buffer) {
   synchronized(buffer) {
            this.value = Arrays.copyOf(buffer.getValue(), buffer.length());
   }
}

因為StringBuffer是線程安全類,所以,這里加了同步鎖,保證線程安全。

public String(StringBuilder builder) {
        this.value = Arrays.copyOf(builder.getValue(), builder.length());
}

StringBuilder是非線程安全的,這里也就沒有做線程安全處理,其他內(nèi)容和前面一樣。

注:很多時候我們不會這么去構(gòu)造,因為StringBuilder跟StringBuffer有toString方法如果不考慮線程安全,優(yōu)先選擇StringBuilder

這里就講這么多構(gòu)造方法,其他很復(fù)雜,也基本不用,所以,了解這些就夠了。如果對其他感興趣的,可以自行去研究研究。

常用方法分析

前面的使用案例中,我們已經(jīng)對String的大部分方法進行演示一波,這里我們就挑幾個相對重要的方法進行深度解析。

hashCode方法

hashCode()方法是在Object類中定義的,String對其進行了重寫。

public int hashCode() {
        int h = hash;
        if (h == 0 && value.length > 0) {
            char val[] = value;
            //hash算法,s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
            //使用{@codeint}算法,其中{@codes[i]}是<i> i</i>字符串的第個字符,
            //{@code n}是字符串,{@code^}表示指數(shù)運算。
            for (int i = 0; i < value.length; i++) {
                h = 31 * h + val[i];
            }
            hash = h;
        }
        return h;
}

hashCode的一個具體實現(xiàn),由于java體系中每個對象都可以轉(zhuǎn)換成String,因此他們應(yīng)該都是通過這個hash來實現(xiàn)的

接著,我們看看equals()方法;

equals()方法

equals()方法也是Object類中定義的,String類對其進行了重寫。

public boolean equals(Object anObject) {
    //首先會判斷是否是同一個對象
     if (this == anObject) {
         return true;
     }
    //判斷是否為String類型
     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) {
                 //不相等,直接返回false
                 if (v1[i] != v2[i])
                     return false;
                 i++;
             }
             return true;
         }
     }
     return false;
}

補充:==比較

==比較基本數(shù)據(jù)類型,比較的是值
==比較引用數(shù)據(jù)類型,比較的是地址值

substring()方法

substring方法在工作使用的也是相當?shù)亩啵饔镁褪墙厝∫欢巫址?/p>

public String substring(int beginIndex) {
    if (beginIndex < 0) {
        throw new StringIndexOutOfBoundsException(beginIndex);
    }
    int subLen = value.length - beginIndex;
    if (subLen < 0) {
        throw new StringIndexOutOfBoundsException(subLen);
    }
    //如果beginIndex==0,返回的是當前對象,
    //否則這里是new的一個新對象,其實String中的很多函數(shù)都是這樣的操作
    return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);
}

intern()方法

intern()方法是native修飾的方法,表示該方法為本地方法。

/*
 * When the intern method is invoked, if the pool already contains a
 * string equal to this {@code String} object as determined by
 * the {@link #equals(Object)} method, then the string from the pool is
 * returned. Otherwise, this {@code String} object is added to the
 * pool and a reference to this {@code String} object is returned.
 */
public native String intern();

方法注釋會有寫到,意思就是調(diào)用方法時,如果常量池有當前String的值,就返回這個值,沒有就加進去,返回這個值的引用。

案例如下

public class StringDemo {
    public static void main(String[] args) throws Exception {
        String str1 = "a";
        String str2 = "b";
        String str3 = "ab";
        String str4 = str1 + str2;
        String str5 = new String("ab");

        System.out.println(str5 == str3);//堆內(nèi)存比較字符串池
        //intern如果常量池有當前String的值,就返回這個值,沒有就加進去,返回這個值的引用
        System.out.println(str5.intern() == str3);//引用的是同一個字符串池里的
        System.out.println(str5.intern() == str4);//變量相加給一個新值,所以str4引用的是個新的
        System.out.println(str4 == str3);//變量相加給一個新值,所以str4引用的是個新的

    }
}

運行結(jié)果

false
true
false
false

length()方法

獲取字符串長度,實際上是獲取字符數(shù)組長度 ,源碼就非常簡單了,沒什么好說的。

public int length() {
    return value.length;
}

isEmpty() 方法

判斷字符串是否為空,實際上是盼復(fù)字符數(shù)組長度是否為0 ,源碼也是非常簡單,沒什么好說的。

public boolean isEmpty() {
    return value.length == 0;
}

charAt(int index) 方法

根據(jù)索引參數(shù)獲取字符 。

public char charAt(int index) {
    //索引小于0或者索引大于字符數(shù)組長度,則拋出越界異常
    if ((index < 0) || (index >= value.length)) {
        throw new StringIndexOutOfBoundsException(index);
    }
    //返回字符數(shù)組指定位置字符
    return value[index];
}

getBytes()方法

獲取字符串的字節(jié)數(shù)組,按照系統(tǒng)默認字符編碼將字符串解碼為字節(jié)數(shù)組 。

public byte[] getBytes() {
    return StringCoding.encode(value, 0, value.length);
}

compareTo()方法

這個方法寫的很巧妙,先從0開始判斷字符大小。如果兩個對象能比較字符的地方比較完了還相等,就直接返回自身長度減被比較對象長度,如果兩個字符串長度相等,則返回的是0,巧妙地判斷了三種情況。

public int compareTo(String anotherString) {
    //自身對象字符串長度len1
    int len1 = value.length;
    //被比較對象字符串長度len2
    int len2 = anotherString.value.length;
    //取兩個字符串長度的最小值lim
    int lim = Math.min(len1, len2);
    char v1[] = value;
    char v2[] = anotherString.value;
 
    int k = 0;
    //從value的第一個字符開始到最小長度lim處為止,如果字符不相等,
    //返回自身(對象不相等處字符-被比較對象不相等字符)
    while (k < lim) {
        char c1 = v1[k];
        char c2 = v2[k];
        if (c1 != c2) {
            return c1 - c2;
        }
        k++;
    }
    //如果前面都相等,則返回(自身長度-被比較對象長度)
    return len1 - len2;
}

startsWith()方法

public boolean startsWith(String prefix, int toffset) {
    char ta[] = value;
    int to = toffset;
    char pa[] = prefix.value;
    int po = 0;
    int pc = prefix.value.length;
    // Note: toffset might be near -1>>>1.
    //如果起始地址小于0或者(起始地址+所比較對象長度)大于自身對象長度,返回假
    if ((toffset < 0) || (toffset > value.length - pc)) {
        return false;
    }
    //從所比較對象的末尾開始比較
    while (--pc >= 0) {
        if (ta[to++] != pa[po++]) {
            return false;
        }
    }
    return true;
}
 
public boolean startsWith(String prefix) {
    return startsWith(prefix, 0);
}
 
public boolean endsWith(String suffix) {
    return startsWith(suffix, value.length - suffix.value.length);
}

起始比較和末尾比較都是比較經(jīng)常用得到的方法,例如:在判斷一個字符串是不是http協(xié)議的,或者初步判斷一個文件是不是mp3文件,都可以采用這個方法進行比較。

concat()方法

public String concat(String str) {
    int otherLen = str.length();
    //如果被添加的字符串為空,返回對象本身
    if (otherLen == 0) {
        return this;
    }
    int len = value.length;
    char buf[] = Arrays.copyOf(value, len + otherLen);
    str.getChars(buf, len);
    return new String(buf, true);
}

concat方法也是經(jīng)常用的方法之一,它先判斷被添加字符串是否為空來決定要不要創(chuàng)建新的對象。

replace()方法

public String replace(char oldChar, char newChar) {
    //新舊值先對比
    if (oldChar != newChar) {
        int len = value.length;
        int i = -1;
        char[] val = value; 
 
        //找到舊值最開始出現(xiàn)的位置
        while (++i < len) {
            if (val[i] == oldChar) {
                break;
            }
        }
        //從那個位置開始,直到末尾,用新值代替出現(xiàn)的舊值
        if (i < len) {
            char buf[] = new char[len];
            for (int j = 0; j < i; j++) {
                buf[j] = val[j];
            }
            while (i < len) {
                char c = val[i];
                buf[i] = (c == oldChar) ? newChar : c;
                i++;
            }
            return new String(buf, true);
        }
    }
    return this;
}

這個方法也有討巧的地方,例如最開始先找出舊值出現(xiàn)的位置,這樣節(jié)省了一部分對比的時間。replace(String oldStr,String newStr)方法通過正則表達式來判斷。

trim()方法

public String trim() {
    int len = value.length;
    int st = 0;
    char[] val = value;    /* avoid getfield opcode */
 
    //找到字符串前段沒有空格的位置
    while ((st < len) && (val[st] <= &#39; &#39;)) {
        st++;
    }
    //找到字符串末尾沒有空格的位置
    while ((st < len) && (val[len - 1] <= &#39; &#39;)) {
        len--;
    }
    //如果前后都沒有出現(xiàn)空格,返回字符串本身
    return ((st > 0) || (len < value.length)) ? substring(st, len) : this;
}

trim方法就是將字符串中的空白字符串刪掉。

valueOf()方法

public static String valueOf(boolean b) {
   //如果b為true就返回"true"否則返回"false"
   return b ? "true" : "false";
}
public static String valueOf(char c) {
    //創(chuàng)建data[]數(shù)組 并把c添加進去
    char data[] = {c};        
     //創(chuàng)建一個新的String對象并進行返回
    return new String(data, true); 
}
public static String valueOf(int i) {
    //調(diào)用Integer對象的toString()方法并進行返回
    return Integer.toString(i);  
}
//Integer類中的toString(i)方法
public static String toString(int i) {
    //是否為Integer最小數(shù),是直接返回
    if (i == Integer.MIN_VALUE)
       return "-2147483648";
    //這個i有多少位
    int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
    //創(chuàng)建一個char數(shù)組
    char[] buf = new char[size];
    //把i內(nèi)容方法char數(shù)組中區(qū)
    getChars(i, size, buf);
    //返回一個String對象
    return new String(buf, true);
}

split() 方法

public String[] split(String regex) {
    return split(regex, 0);
}
//使用到了正則表達式
public String[] split(String regex, int limit) {
      //....
    //源碼有點多了,反正就是里面使用到了正則表達式,進行切分
    }

split() 方法用于把一個字符串分割成字符串數(shù)組,返回一個字符串數(shù)組返回的數(shù)組中的字串不包括 regex自身??蛇x的“limit”是一個整數(shù),第一個方法中默認是0,允許各位指定要返回的最大數(shù)組的元素個數(shù)。

常見方法源碼分析就這么多了,下面我們再回顧到使用場景中來,尤其是面試中。

String在面試中常見問題

如何比較字符串相同?

在java中比較對象是否相同,通常有兩種方法:

  • ==
  • equals方法

注意==用于基本數(shù)據(jù)類型的比較和用于引用類型的比較的區(qū)別。

==比較基本數(shù)據(jù)類型,比較的是值

==比較引用數(shù)據(jù)類型,比較的是地址值

另外,Stringequals方法進行了重寫,所以比較字符串咱們還是要使用equals方法來比較。主要是Stringequals方法里包含了==的判斷(請看前面源碼分析部分)。

案例

public class StringDemo {
   public static void main(String[] args) {
     String st1 = "abc";
     String st2 = "abc";
     System.out.println(st1 == st2);
     System.out.println(st1.equals(st2)); 
   }
}

輸出

true
true

String str=new String("abc");這行代碼創(chuàng)建了幾個對象?

看下面這段代碼:

String str1 = "abc";  // 在常量池中
String str2 = new String("abc"); // 在堆上

關(guān)于這段代碼,創(chuàng)建了幾個對象,網(wǎng)上答案有多重,1個,2個還有3個的。下面我們就來聊聊到底是幾個?

まず、str1 であっても str2 であっても、それらはすべて String 型の変數(shù)であり、オブジェクトではないことを明確にする必要があります。通常は、これを str2 オブジェクトと呼ぶことがあります。これは、理解を容易にするためです。本質(zhì)的には、 、str2 と str1 は両方ともオブジェクトではありません。

2 番目に、String str="abc"; という文字列 "abc" が文字列定數(shù)プールに 1 つのコピーだけ保存されます。このときの代入演算は次と同じです。 0 または 1 つのオブジェクトを作成します。 「abc」が定數(shù)プールにすでに存在する場合、オブジェクトは作成されず、參照は str1 に直接割り當てられます?!竌bc」が定數(shù)プールに存在しない場合、オブジェクトが作成され、參照は str1 に割り當てられます。 str1。

それでは、 new String("abc"); の形式はどうなるのでしょうか?

答えは 1 または 2 です。

JVM が上記のコードに遭遇すると、まず定數(shù)プールに "abc" が存在するかどうかを検索します。文字列 "abc" が存在しない場合は、まず定數(shù)內(nèi)にこの文字を作成します。プールの文字列。次に、新しい操作を?qū)g行すると、「abc」を格納する String オブジェクトがヒープ メモリに作成され、そのオブジェクトの參照が str2 に割り當てられます。このプロセスにより 2 つのオブジェクトが作成されます。

もちろん、定數(shù)プールの取得時に対応する文字列が見つかった場合、ヒープには新しい String オブジェクトのみが作成され、このプロセスではオブジェクトが 1 つだけ作成されます。

最後に、String str=new String("abc"); とすると、いくつかのオブジェクトが作成されます。覚えておいてください: "abc" が定數(shù)プールに存在するかどうか、存在する場合は作成します。オブジェクト ; 2 つのオブジェクトが作成されることはありません。

String と StringBuilder および StringBuffer の違い

スレッド セーフティ

String 內(nèi)のオブジェクトは不変であり、定數(shù)として理解できるため、スレッド セーフです。 AbstractStringBuilder は StringBuilder と StringBuffer の共通の親クラスであり、expandCapacity、append、insert、indexOf、その他のパブリック メソッドなどのいくつかの基本的な文字列操作を定義します。 StringBuffer はメソッドに同期ロックを追加するか、呼び出し側(cè)メソッドに同期ロックを追加するため、スレッドセーフです。 StringBuilder はメソッドに同期ロックを追加しないため、スレッドセーフではありません。

パフォーマンス

String 型が変更されるたびに、新しい String オブジェクトが生成され、ポインターは新しい String オブジェクトを指します。 StringBuffer は、新しいオブジェクトを生成したりオブジェクト參照を変更したりするのではなく、毎回 StringBuffer オブジェクト自體を操作します。同じ狀況下で、StringBuilder を使用すると、StringBuffer を使用した場合と比較して約 10% ~ 15% のパフォーマンス向上しか達成できませんが、マルチスレッドのセキュリティが確保されないリスクがあります。

3 つの使用法に関するまとめ:

  • 操作少量的數(shù)據(jù) ,推薦使用String
  • 單線程操作字符串緩沖區(qū)下操作大量數(shù)據(jù),推薦使用 StringBuilder
  • 多線程操作字符串緩沖區(qū)下操作大量數(shù)據(jù) ,推薦使用 StringBuffer

String 和 JVM有什么關(guān)系?

String 常見的創(chuàng)建方式有兩種,new String() 的方式和直接賦值的方式,直接賦值的方式會先去字符串常量池中查找是否已經(jīng)有此值,如果有則把引用地址直接指向此值,否則會先在常量池中創(chuàng)建,然后再把引用指向此值;而 new String() 的方式一定會先在堆上創(chuàng)建一個字符串對象,然后再去常量池中查詢此字符串的值是否已經(jīng)存在,如果不存在會先在常量池中創(chuàng)建此字符串,然后把引用的值指向此字符串。

JVM中的常量池

2wワード詳細説明文字列、yyds


字面量—文本字符串,也就是我們舉例中的 public String s = " abc "; 中的 "abc"。

用 final 修飾的成員變量,包括靜態(tài)變量、實例變量和局部變量。

請看下面這段代碼:

String s1 = new String("Java");
String s2 = s1.intern();
String s3 = "Java";
System.out.println(s1 == s2); // false
System.out.println(s2 == s3); // true

它們在 JVM 存儲的位置,如下圖所示:

2wワード詳細説明文字列、yyds


注意:JDK 1.7 之后把永生代換成的元空間,把字符串常量池從方法區(qū)移到了 Java 堆上。

除此之外編譯器還會對 String 字符串做一些優(yōu)化,例如以下代碼:

String s1 = "Ja" + "va";
String s2 = "Java";
System.out.println(s1 == s2);

雖然 s1 拼接了多個字符串,但對比的結(jié)果卻是 true,我們使用反編譯工具,看到的結(jié)果如下:

Compiled from "StringExample.java"
public class com.lagou.interview.StringExample {
  public com.lagou.interview.StringExample();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return
    LineNumberTable:
      line 3: 0
  public static void main(java.lang.String[]);
    Code:
       0: ldc           #2                  // String Java
       2: astore_1
       3: ldc           #2                  // String Java
       5: astore_2
       6: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
       9: aload_1
      10: aload_2
      11: if_acmpne     18
      14: iconst_1
      15: goto          19
      18: iconst_0
      19: invokevirtual #4                  // Method java/io/PrintStream.println:(Z)V
      22: return
    LineNumberTable:
      line 5: 0
      line 6: 3
      line 7: 6
      line 8: 22
}

從編譯代碼 #2 可以看出,代碼 "Ja"+"va" 被直接編譯成了 "Java" ,因此 s1==s2 的結(jié)果才是 true,這就是編譯器對字符串優(yōu)化的結(jié)果。

如何判斷兩個字符串中含有幾個相同字符

  • 將字符串轉(zhuǎn)化成數(shù)組
  • HashMap 方法
  • 字符串直接進行比較
  • 正則表達式
  • HashSet 方法

String有沒有長度限制?是多少?為什么?

下面先看看length方法源碼:

private final char value[];
public int length() {
        return value.length;
}

length()方法返回的是int類型,那可以得知String類型的長度肯定不能超過Integer.MAX_VALUE的。

答:首先字符串的內(nèi)容是由一個字符數(shù)組 char[] 來存儲的,由于數(shù)組的長度及索引是整數(shù),且String類中返回字符串長度的方法length() 的返回值也是int ,所以通過查看java源碼中的類Integer我們可以看到Integer的最大范圍是2^31 -1,由于數(shù)組是從0開始的,所以**數(shù)組的最大長度可以使【0~2^31】**通過計算是大概4GB。

但是通過翻閱java虛擬機手冊對class文件格式的定義以及常量池中對String類型的結(jié)構(gòu)體定義我們可以知道對于索引定義了u2,就是無符號占2個字節(jié),2個字節(jié)可以表示的最大范圍是2^16 -1 = 65535。

但是由于JVM需要1個字節(jié)表示結(jié)束指令,所以這個范圍就為65534了。超出這個范圍在編譯時期是會報錯的,但是運行時拼接或者賦值的話范圍是在整形的最大范圍。

字符串對象能否用在switch表達式中?

JDK7開始的話,我們就可以在switch條件表達式中使用字符串了,也就是說7之前的版本是不可以的。

switch (str.toLowerCase()) {
      case "tian":
           value = 1;
           break;
      case "jiang":
           value = 2;
           break;
}

說說String中intern方法

JDK7之前的版本,調(diào)用這個方法的時候,會去常量池中查看是否已經(jīng)存在這個常量了,如果已經(jīng)存在,那么直接返回這個常量在常量池中的地址值,如果不存在,則在常量池中創(chuàng)建一個,并返回其地址值。

但是在JDK7以及之后的版本中,常量池從perm區(qū)搬到了heap區(qū)。intern檢測到這個常量在常量池中不存在的時候,不會直接在常量池中創(chuàng)建該對象了,而是將堆中的這個對象的引用直接存到常量池中,減少內(nèi)存開銷。

下面的案例

public class InternTest {
  
  public static void main(String[] args) {
    String str1 = new String("hello") + new String("world");
    str1.intern();
    String str2 = "helloworld";
    System.out.println(str1 == str2);//true
    System.out.println(str1.intern() == str2);//true
  }
}

好了,關(guān)于Stirng類的分享就到此,歡迎找我探討更多技術(shù)問題。

以上が2wワード詳細説明文字列、yydsの詳細內(nèi)容です。詳細については、PHP 中國語 Web サイトの他の関連記事を參照してください。

このウェブサイトの聲明
この記事の內(nèi)容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰屬します。このサイトは、それに相當する法的責任を負いません。盜作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡(luò)ください。

ホットAIツール

Undress AI Tool

Undress AI Tool

脫衣畫像を無料で

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード寫真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

寫真から衣服を削除するオンライン AI ツール。

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中國語版

SublimeText3 中國語版

中國語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統(tǒng)合開発環(huán)境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Java の String.valueOf() 関數(shù)を使用して基本データ型を文字列に変換する Java の String.valueOf() 関數(shù)を使用して基本データ型を文字列に変換する Jul 24, 2023 pm 07:55 PM

Java の String.valueOf() 関數(shù)を使用して基本データ型を文字列に変換する Java 開発で基本データ型を文字列に変換する必要がある場合、一般的な方法は String クラスの valueOf() 関數(shù)を使用することです。この関數(shù)は、基本データ型のパラメータを受け入れ、対応する文字列表現(xiàn)を返すことができます。この記事では、基本的なデータ型変換に String.valueOf() 関數(shù)を使用する方法を検討し、いくつかのコード例を提供します。

char配列を文字列に変換する方法 char配列を文字列に変換する方法 Jun 09, 2023 am 10:04 AM

char配列をstringに変換する方法:代入によって実現(xiàn)できます {char a[]=" abc d\0efg ";string s=a;} 構(gòu)文を使用して、char配列にstringに値を直接代入させて実行します変換を完了するためのコード。

Java の String.replace() 関數(shù)を使用して、文字列內(nèi)の文字 (文字列) を置換します。 Java の String.replace() 関數(shù)を使用して、文字列內(nèi)の文字 (文字列) を置換します。 Jul 25, 2023 pm 05:16 PM

Java の String.replace() 関數(shù)を使用して文字列內(nèi)の文字 (文字列) を置換する Java では、文字列は不変オブジェクトです。つまり、文字列オブジェクトが作成されると、その値は変更できません。ただし、文字列內(nèi)の特定の文字または文字列を置換する必要がある狀況が発生する場合があります。現(xiàn)時點では、Java の String クラスの replace() メソッドを使用して文字列置換を?qū)g裝できます。 String クラスの replace() メソッドには 2 つのタイプがあります。

JavaのString.length()関數(shù)を使用して文字列の長さを取得します。 JavaのString.length()関數(shù)を使用して文字列の長さを取得します。 Jul 25, 2023 am 09:09 AM

文字列の長さを取得するには、Java の String.length() 関數(shù)を使用します。Java プログラミングでは、文字列は非常に一般的なデータ型です。多くの場合、文字列の長さ、つまり文字列內(nèi)の文字數(shù)を取得する必要があります。 Java では、String クラスの length() 関數(shù)を使用して文字列の長さを取得できます。簡単なコード例を次に示します。 publicclassStringLengthExample{publ

2wワード詳細説明文字列、yyds 2wワード詳細説明文字列、yyds Aug 24, 2023 pm 03:56 PM

皆さんこんにちは。今日は Java の基本知識である String についてお話します。 String クラスの重要性は言うまでもなく、バックエンド開発で最もよく使用されるクラスであるため、説明する必要があります。

Java の String.startsWith() 関數(shù)を使用して、文字列が指定されたプレフィックスで始まるかどうかを判斷します Java の String.startsWith() 関數(shù)を使用して、文字列が指定されたプレフィックスで始まるかどうかを判斷します Jul 25, 2023 pm 02:27 PM

Java の String.startsWith() 関數(shù)を使用して、文字列が指定されたプレフィックスで始まるかどうかを確認します。Java プログラミングでは、多くの場合、文字列を処理して決定する必要があります。一般的な操作の 1 つは、文字列が指定されたプレフィックスで始まるかどうかを判斷することです。 Java では、この関數(shù)を簡単に実裝できる String クラスの startWith() 関數(shù)が提供されています。 String のstartsWith() 関數(shù) String クラスは Java で最も一般的に使用されるクラスです

JavaのStringクラスの使い方 JavaのStringクラスの使い方 Apr 19, 2023 pm 01:19 PM

1. JDK の String1. String を理解する まず、JDK の String クラスのソース コードを見てみましょう. これには多くのインターフェイスが実裝されています. String クラスは Final によって変更されていることがわかります. これは、String クラスができないことを意味しますString. クラスのサブクラスは継承されず、String. クラスのサブクラスは存在しないため、JDK を使用するすべての人が同じ String クラスを使用します。String の継承が許可されている場合、誰もが String を拡張できます。全員が異なるバージョンの String を使用し、2 人の異なる人が String. クラスを使用します。同じメソッドでも異なる結(jié)果が表示されるため、コードの開発が不可能になります。継承とメソッドのオーバーライドは柔軟性をもたらすだけでなく、多くのサブクラスの動作が異なる原因になります。

JavaのString.toLowerCase()関數(shù)を使用して文字列を小文字に変換します。 JavaのString.toLowerCase()関數(shù)を使用して文字列を小文字に変換します。 Jul 24, 2023 pm 11:52 PM

String.toLowerCase() 関數(shù)は、文字列を小文字に変換できる、Java の非常に便利な一般的な文字列処理関數(shù)です。この記事では、この関數(shù)の使用方法と関連するコード例をいくつか紹介します。まず、String.toLowerCase() 関數(shù)の基本構(gòu)文を見てみましょう。パラメータはありません。ただ呼び出すだけです。サンプルコードは次のとおりです: Stringstr="Hel

See all articles