你应该了解的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));
    }
}

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