国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Java字符串的intern方法有何奧妙之處

Java字符串的intern方法有何奧妙之處

2022-02-13 14:41吾日三省賈斯汀 Java教程

intern() 方法返回字符串對象的規(guī)范化表示形式。它遵循以下規(guī)則:對于任意兩個字符串 s 和 t,當且僅當 s.equals(t) 為 true 時,s.intern() == t.intern() 才為 true

學習背景

進入正文學習字符串intern()方法之前,先給下這4個問題,看下自己是否都知道答案?

1、String s1 = “a” + “b”; //創(chuàng)建了幾個對象?
2、String s2 = new String(“ab”); //創(chuàng)建了幾個對象?
3、String s3 = new String(“a”) + new String(“b”); //創(chuàng)建了幾個對象?
4、String s4= new String(“a”) + new String(“a”); s4.intern(); //創(chuàng)建了幾個對象?

如果都清楚,恭喜你,大佬一枚,不用往下學習了,哈哈哈!
那如果不太確定或者需要加深自己的理解,建議進入正文一起來了解下吧!
當然,也可以拉到最后有答案!

String#intern()示例代碼

先來執(zhí)行一下String調(diào)用intern()方法的一段示例代碼:

public class StringInternTest {
    public static void main(String[] args) {
        String reference1 = new String("a");
        reference1.intern();
        String reference2 = "a";
        System.out.println(reference1 == reference2);

        String reference3 = new String("a") + new String("a");
        reference3.intern();
        String reference4 = "aa";
        System.out.println(reference3 == reference4);
    }
}

JDK1.6 執(zhí)行輸出結果:

false
false

JDK1.7 執(zhí)行輸出結果:

false
true

大家可以先思考一下為什么結果是這樣的?往下會具體介紹!

String##intern()源碼

先來看一下intern()方法的JDK源碼如下:

    /**
     * Returns a canonical representation for the string object.
     * <p>
     * A pool of strings, initially empty, is maintained privately by the
     * class {@code String}.
     * <p>
     * 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.
     * <p>
     * It follows that for any two strings {@code s} and {@code t},
     * {@code s.intern() == t.intern()} is {@code true}
     * if and only if {@code s.equals(t)} is {@code true}.
     * <p>
     * All literal strings and string-valued constant expressions are
     * interned. String literals are defined in section 3.10.5 of the
     * <cite>The Java&trade; Language Specification</cite>.
     *
     * @return  a string that has the same contents as this string, but is
     *          guaranteed to be from a pool of unique strings.
     */
    public native String intern();

很顯然通過源碼可以看到intern()是一個native本地方法,但是native具體實現(xiàn)源碼已經(jīng)被隱藏了,這是一個歷史故事了,SUN公司在JDK7開發(fā)期間,由于技術競爭和商業(yè)競爭陷入泥潭,無力再投入精力繼續(xù)研發(fā)JDK,Oracle半路殺出直接收購Sun公司,Oracle接管JDK的研發(fā)后,發(fā)版了自己的Oracle JDK,Oracle的native底層等很多源碼就被隱藏了,不過Oracle官方也聲明OpenJDK和Oracle JDK7及以后版本,源碼幾乎是一模一樣的,想要了解native底層源碼具體實現(xiàn)過程,可以下載開源的OpenJDK的源碼進行查看。

OpenJDK官網(wǎng):https://hg.openjdk.java.net/
GitHub也開源啦:https://github.com/openjdk/jdk

例如String對應的OpenJDK底層源碼主入口:jdk7jdksrcshare ativejavalangString.c

Java_java_lang_String_intern(JNIEnv *env, jobject this)
{
    return JVM_InternString(env, this);
}

native底層方法的實現(xiàn),需要掌握C和C++的語法,學習門檻要求比較高,這里不是我們要學習的重點,不做具體介紹。

String#intern()方法作用

前面JDK源碼intern()方法的英文注釋已經(jīng)說明了intern()方法的有具體用途了,網(wǎng)上也有很多說明,不過這里我以個人的理解以及話術簡單概括下intern()方法的作用如下:

(1)只要調(diào)用String對象的intern(),都會去找到字符串常量池,然后判斷String對象的字符串內(nèi)容是否已經(jīng)存在常量池中,不存在,則往字符串常量池中創(chuàng)建該字符串內(nèi)容的對象(JDK6及之前)或創(chuàng)建新的引用并指向堆區(qū)已有對象地址(JDK7之后),存在則直接返回。

(2)JDK7時,字符串常量池從永久代脫離,遷移到堆區(qū)中,相比于JDK6,變化不只是字符串常量池遷移到堆區(qū)而已,另一個變化就是調(diào)用字符串對象的intern()方法,如果字符串常量池中不存在該字符串內(nèi)容的對象,則不會再像JDK6直接往字符串常量池中創(chuàng)建該字符串內(nèi)容的對象,而是創(chuàng)建一個新的引用并指向堆區(qū)已有對象地址,實現(xiàn)字符串常量池和堆區(qū)字符串共用的目的,效率更高。

JDK6 String#intern()執(zhí)行說明

一張圖介紹前面示例代碼JDK6執(zhí)行過程如下:

Java字符串的intern方法有何奧妙之處

/**
 * JDK6 String#intern()執(zhí)行說明
 */
public class StringInternTest {
    public static void main(String[] args) {
        //Step6.1
        //創(chuàng)建了2個對象,分別是堆區(qū)的String對象和字符串常量池中的"a"對象,reference1引用指向在堆區(qū)中的對象地址
        String reference1 = new String("a");
        //Step6.2
        //判斷字符串常量池,是否該字符串"a",此前,池中已經(jīng)有該對象了,因此會返回池中的對象地址的引用
        reference1.intern();
        //Step6.3
        //字符串常量池中已存在字符串"a",因此reference2引用直接指向?qū)ο笤谧址A砍刂械牡刂?
        String reference2 = "a";
        //reference1指向?qū)ο蟮刂肥窃诙褏^(qū),reference2指向?qū)ο蟮刂肥窃谟谰么某A砍兀@然不可能一樣
        System.out.println(reference1 == reference2);

        //Step6.4
        //創(chuàng)建了2個對象,分別是在堆區(qū)的String對象(內(nèi)容是"aa")和字符串常量池中的"a"對象
        //reference3引用指向?qū)ο笤诙褏^(qū)中的地址,這過程還會在堆區(qū)創(chuàng)建了兩個無引用的"a"對象,這里不做討論
        String reference3 = new String("a") + new String("a");
        //Step6.5
        //判斷永久代中的字符串常量池,是否存在該字符串"aa",這里是首次出現(xiàn),因此直接將字符串拷貝并放到池中
        reference3.intern();
        //Step6.6
        //池中已存在該字符串,reference2引用直接指向?qū)ο笤谟谰么址A砍刂械牡刂?
        String reference4 = "aa";
        //同樣,reference3指向堆區(qū)地址,reference4指向永久代常量池中的地址,顯然不可能一樣
        System.out.println(reference3 == reference4);
    }
}

JDK7 String#intern()執(zhí)行說明

一張圖介紹前面示例代碼JDK7執(zhí)行過程如下:

Java字符串的intern方法有何奧妙之處

/**
 * JDK1.7 String#intern()執(zhí)行說明
 **/
public class StringInternTest {
    public static void main(String[] args) {
        //Step7.1
        //創(chuàng)建了2個對象,分別是堆區(qū)的String對象和字符串常量池中的"a"對象,reference1引用指向在堆區(qū)中的對象地址
        String reference1 = new String("a");
        //Step7.2
        //判斷字符串常量池,是否該字符串"a",此前,池中已經(jīng)有該對象了,因此會返回池中的對象地址的引用
        reference1.intern();
        //Step7.3
        //字符串常量池中已存在字符串"a",因此reference2引用直接指向?qū)ο笤谧址A砍刂械牡刂?
        String reference2 = "a";
        //reference1指向?qū)ο蟮刂肥窃诙褏^(qū),reference2指向?qū)ο蟮刂肥窃诙褏^(qū)的字符串常量池,引用指向的對象地址不一樣
        System.out.println( reference1 == reference2);

        //Step7.4
        //創(chuàng)建了2個對象,分別是在堆區(qū)的String對象(內(nèi)容是"aa")和字符串常量池中的"a"對象(注意并不會創(chuàng)建"aa"對象)
        //reference3引用指向?qū)ο笤诙褏^(qū)中的地址,這過程還會在堆區(qū)創(chuàng)建了兩個無引用的"a"對象,這里不做討論
        String reference3 = new String("a") + new String("a");
        //Step7.5
        //判斷堆區(qū)的字符串常量池中,是否存在該字符串"aa",顯然這里是首次出現(xiàn)
        //但并不像JDK6會新建對象"aa"存儲,而是存儲指向堆區(qū)已有對象地址的一個新引用
        reference3.intern();
        //Step7.6
        //指向池中已有該字符串的新引用,reference4引用直接指向字符串常量池中的這個新引用,新引用則指向堆區(qū)已有對象地址
        String reference4 = "aa";
        //reference4指向新引用,而新引用則指向堆區(qū)已有對象地址,跟reference3引用直接指向的對象地址是同一個
        System.out.println(reference3 == reference4);
    }

經(jīng)典面試問題之創(chuàng)建了幾個對象?

在實際的Java面試當中,經(jīng)常會被問到字符串創(chuàng)建了幾個對象的問題,主要是考察學習者對于對象的實例化以及字符串常量池在JVM結構體系中是如何運行的,個人覺得比較常見問題,無法就是如下幾個:

1、最簡單的比如:String s1 = “a” + “b”;創(chuàng)建了幾個對象?

答:最多1個,多個字符串常量相加會被編譯器優(yōu)化為一個字符串常量即"ab",如果字符串常量池不存在,則創(chuàng)建該對象。

2、相對簡單的比如:String s1 = new String(“ab”);創(chuàng)建了幾個對象?

答:1個或2個,使用new實例化對象,必然會在堆區(qū)創(chuàng)建一個對象,另外一個就是如果在字符串常量池中不存在"ab"這個對象,則會創(chuàng)建這個"ab"常量對象。

3、稍微難一點的比如:String s2 = new String(“a”) + new String(“b”);創(chuàng)建了幾個對象?

答:至少4個,最多6個
堆區(qū)的1個new StringBuilder()和2個new String()
還有1個是StringBuilder()的toString()方法底層實現(xiàn)是new String(value, 0, count)
另外2個即"a"、"b"可能會在常量池新建對象
有的同學可能會有疑問,那這個toString過程"ab"字符串不會在常量池中也創(chuàng)建嗎?
答案是,不會,最后StringBuilder的toString() 的調(diào)用,底層new String(value, 0, count) 并不會在字符串常量池中去創(chuàng)建"ab"對象。
兩個new String相加會被優(yōu)化為StringBuilder,可以通過javac和javap查看匯編指令如下:
javac InternTest.java
javap -c InternTest

public class com.justin.java.lang.InternTest {
  public com.justin.java.lang.InternTest();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: new           #2                  // class java/lang/StringBuilder
       3: dup
       4: invokespecial #3                  // Method java/lang/StringBuilder."<init>":()V
       7: new           #4                  // class java/lang/String
      10: dup
      11: ldc           #5                  // String a
      13: invokespecial #6                  // Method java/lang/String."<init>":(Ljava/lang/String;)V
      16: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      19: new           #4                  // class java/lang/String
      22: dup
      23: ldc           #8                  // String b
      25: invokespecial #6                  // Method java/lang/String."<init>":(Ljava/lang/String;)V
      28: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      31: invokevirtual #9                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      34: astore_1
      35: return
}

最難的無非就是再調(diào)用intern()方法,比如:
String s3= new String(“a”) + new String(“b”);
s3.intern();創(chuàng)建了幾個對象?

答:最少4個,最多7個
1個new StringBuilder()和2個new String
還有1個是StringBuilder()的toString()方法底層實現(xiàn)是new String(value, 0, count)
另外"a"、“b"可能會在常量池新建對象
最后調(diào)用intern()方法時,會去字符串常量池,判斷"ab"是否存在,不存在,JDK6時會創(chuàng)建"ab” 1個對象,JDK7則只創(chuàng)建"ab"的引用并指向堆區(qū)內(nèi)容為"ab"的StringBuilder對象地址。

到此這篇關于Java字符串的intern方法有何奧妙之處的文章就介紹到這了,更多相關Java intern方法內(nèi)容請搜索服務器之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持服務器之家!

原文鏈接:https://blog.csdn.net/JustinQin/article/details/120606343

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 国产精品影视 | 青青国产视频 | 午夜影视 | 日韩电影一区 | 在线中文视频 | 小泽玛丽娅 | 国产精品成人在线视频 | 久久综合一区二区三区 | 欧美日韩亚洲成人 | 国产精品免费自拍 | 亚洲综合二区 | 亚洲精品免费在线 | 欧美高清一区 | 中文字幕在线观看一区二区 | 中文字幕91视频 | 国产黄色片一级 | 午夜欧美一区二区三区在线播放 | 99精品久久 | 女人夜夜春高潮爽av片 | 日韩一区在线观看视频 | 亚洲综合在线视频 | 在线播放国产一区二区三区 | 国产精品1| 狠狠se | 亚洲精品乱码久久久久久蜜糖图片 | 欧美日韩免费 | 日韩免费在线视频 | 久久91久久久久麻豆精品 | 欧美精品在欧美一区二区少妇 | 中文字幕二区 | 欧美大片免费高清观看 | 在线观看午夜 | 久久久久久毛片免费播放 | 久久精品国产99国产 | 日韩欧美中文在线观看 | 激情成人综合 | 91精品国产高清一区二区三区 | 国产一区二区三区久久 | 国产剧情一区二区 | 一级做a爰片久久高潮 | 国产一级二级毛片 |