你應該瞭解的JAVA基礎-----String

前言

  String這種東西天天都在用,但是還真的沒有專門研究過,只是之前簡單看過一些介紹。今天專門研究一下,加深一些印象,這些基礎知識都是JAVA程序員(非碼農)必須應該具備的硬實力。

實驗代碼

package com.java.example.demo.string;

/**
 * 練習String知識點
 */
public class StringDemo {
    public static void main(String[] args) {
        String str1 = "zhaoxiaoluo";
        String str2 = "zhaoxiaoluo";
        String str3 = "zhao" + "xiaoluo";
        String temp = "xiaoluo";
        String str4 = "zhao" + temp;
        String str5 = new String("zhaoxiaoluo");
        String str6 = new String("zhaoxiaoluo");
        String str7 = str6.intern();

        // == 比較是否是同一個引用
        System.out.println("str1 str2:" + (str1 == str2));
        System.out.println("str1 str3:" + (str1 == str3));
        System.out.println("str1 str4:" + (str1 == str4));
        System.out.println("str1 str5:" + (str1 == str5));
        System.out.println("str1 str7:" + (str1 == str7));
        System.out.println("str5 str6:" + (str5 == str6));
        System.out.println("str5 str7:" + (str5 == str7));

        //使用equals比較值
        System.out.println("下面是equals:");
        System.out.println(str1.equals(str2));
        System.out.println(str1.equals(str3));
        System.out.println(str1.equals(str4));
        System.out.println(str1.equals(str5));
        System.out.println(str1.equals(str7));
        System.out.println(str5.equals(str6));
        System.out.println(str5.equals(str7));
    }
}

執行結果

str1 str2:true
str1 str3:true
str1 str4:false
str1 str5:false
str1 str7:true
str5 str6:false
str5 str7:false
下面是equals:
true
true
true
true
true
true
true

理論知識補充

  字符串的分配,和其他對象分配一樣會耗費大量時間和空間代價。JVM爲了提升性能和減少消耗,在實例化字符串常量時進行了一些優化。由於字符串的不可變性,爲了減少在JVM中創建字符串的數量,Java維護了一個字符串常量池。每當有字符串常量被創建時,JVM會首先檢查字符串常量池中是否已存在該字符串。若存在,返回該對象的引用。若不存在,實例化該字符串放在常量池中。

  Java的堆內存是專門用來存放對象的,若使用new String這種形式,會生成一個新的String對象,強制存放在了堆內存中,就不會去和常量池作比較,所以引用地址是不一致的。

  intern()方法是強制返回常量池中的對象引用,若常量池中已存在,則返回對應常量池中的引用,若不存在,實例化後放入常量池,返回該引用。

解析版代碼

package com.java.example.demo.string;

/**
 * 練習String知識點(解析版)
 */
public class StringDemo2 {
    public static void main(String[] args) {
        //1、去常量池中查詢,沒有“zhaoxiaoluo”,實例化並放入常量池
        String str1 = "zhaoxiaoluo";
        //2、去常量池中查詢,有“zhaoxiaoluo”,直接返回該引用,所以此處和str1指向的是同一個常量池地址
        String str2 = "zhaoxiaoluo";
        //3、編譯期會將 兩個常量拼接在一起,然後去常量池中查詢“zhaoxiaoluo”,同str2
        String str3 = "zhao" + "xiaoluo";
        //4、由於涉及了變量,運行時纔會拼接在一起(非編譯期),其內部實現是先new一個StringBuild,
        //stringBuild.append("zhao").append(temp).toString();所以是返回了一個新的對象
        String temp = "xiaoluo";
        String str4 = "zhao" + temp;
        //5、使用 new String創建了一個 String對象,所以強制放在了堆內存中(堆內存放對象實例),
        // 沒有和常量池比對,也沒有放在常量池,所以和str1不是一個地址
        String str5 = new String("zhaoxiaoluo");
        //6、同str5,會存放在堆內存中,堆內存中每次都是新增對象(無論值是否相等)
        String str6 = new String("zhaoxiaoluo");
        //7、intern()方法的作用就是,返回一個字符串常量池中的引用,
        // 若常量池中存在該字符串,返回引用,否則,在常量池中新增該字符串
        String str7 = str6.intern();

        // == 比較是否是同一個引用
        System.out.println("str1 str2:" + (str1 == str2));
        System.out.println("str1 str3:" + (str1 == str3));
        System.out.println("str1 str4:" + (str1 == str4));
        System.out.println("str1 str5:" + (str1 == str5));
        System.out.println("str1 str7:" + (str1 == str7));
        System.out.println("str5 str6:" + (str5 == str6));
        System.out.println("str5 str7:" + (str5 == str7));

        //如果用equals比較值的話,因爲所有的值都是“zhaoxiaoluo”,所以都是相等的
        System.out.println("下面是equals:");
        System.out.println(str1.equals(str2));
        System.out.println(str1.equals(str3));
        System.out.println(str1.equals(str4));
        System.out.println(str1.equals(str5));
        System.out.println(str1.equals(str7));
        System.out.println(str5.equals(str6));
        System.out.println(str5.equals(str7));
    }
}

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