简述String类型

要了解String类型的特性,首先了解java的基础知识。

一、 基本数据类型和引用数据类型

JVM中使用栈来存储方法以及非全局的变量,对于基本类型来说,栈中既存变量又存值,基本类型有8种:boolean, byte,short,int, long,float, double, char, 不是基本类型的类型称为引用类型,对于引用类型来说,栈中存变量及对象内存地址,对象内存地址指向实际对象实例。String 就是引用数据类型。基本数据类型之间的比较使用"==", 引用类型比较通常有特定的方法如equals方法。

二、 字符串常量池

String 作为引用类型,正常来说创建应该是String str = new String("Hello");,但是String太常用,几乎每一个类型都包含这个类型的对象,这样创建String对象就会带来大量的时间和空间开销,影响程序的性能,所以JVM对String类型的创建做了优化,设计了字符串常量池替代new创建String类型,变成了String str = "Hello";String类型在创建时首先会去字符串常量池中查找是否存在该字符串,如果没有则创建改字符串,如果有,则将引用指向该字符串。这样设计多个变量就会指向同一个字符串对象,一个变量修改就会影响另外的引用,为了消除这种影响,String类型被设计为final修饰。字符串常量池存在JVM方法区,所以里面的字符串不会被轻易回收。

三、 方法参数的值传递和引用传递

在java中,方法参数的值传递和引用传递对应基本数据类型和引用数据类型,基本数据类型参数是值传递,引用数据类型是参数传递。值传递的特点是方法传参数时,会将原变量(基本数据类型变量和值存一起)拷贝一个副本传入方法,方法中对拷贝的副本操作并不会影响原变量。引用传递也会将原变量拷贝一个副本传入方法,但是由于变量存的是引用地址,所以方法中对变量的修改会影响原变量。String是引用数据类型,也就有引用传递的特点,但是java中String是fina修饰的,也就是不可变的,传入方法也不会被修改。

四、 String的创建

    public static void main(String[] args) {
        String str = "Hello";
        String str2 = "Hello";

        String str3 = new String("Hello");
        String str4 = new String("Hello");

        String str5 = str;

        System.out.println("str == str2:" + (str == str2));
        System.out.println("str == str3:" + (str == str3));
        System.out.println("str3 == str4:" + (str3 == str4));
        System.out.println("str2 == str5:" + (str2 == str5));
        System.out.println("str equals str3:" + (str.equals(str3)));
    }
  • String str = "Hello" 在创建时会在字符创常量池创建字符串对象 "Hello",
  • String str2 = "Hello" 在创建时会在字符创常量池查找"Hello", 发现已存在,会指向"Hello", str == str2为true。
  • str3 和 str4 在创建时都会在堆中new一个新对象实例,所以str == str3 和 str3 == str4 都是false
  • String str5 = str中,str5也是指向常量池字符串, 所以 str2 == str5 为true
  • String重写了equals方法,比较是两个String对象的值,所以str.equals(str3)为true

执行结果:

str == str2:true
str == str3:false
str3 == str4:false
str2 == str5:true
str equals str3:true

图解String的创建:

5. String类型的参数传递

    public static void main(String[] args) {
        int ii = 10;
        Map<String, String> map = new HashMap<>();
        map.put("key", "Hello");
        String str = "Hello";
        String str2 = new String("Hello");
        change1(ii);
        System.out.println("ii: " + ii);
        change2(map);
        System.out.println("map: " + JSON.toJSONString(map));
        change3(str);
        System.out.println("str: " + str);
        change4(str2);
        System.out.println("str2: " + str2);

    }
    public static void change1(int ii) {
        ii = 50;
    }
    public static void change2(Map<String, String> map) {
        map.put("key", "world");
    }
    public static void change3(String str) {
        str = "你好!";
    }
    public static void change4(String str2) {
        str2 = new String("你好!");
    }
  • ii变量是基本数据类型int,chang1方法执行是拷贝了ii的副本并修改并不能改变ii的值。
  • map变量是引用数据类型,chang2方法中操作的map和原map变量都指向同一个HashMap对象,所以chang2方法对map的修改会影响到原map
  • str和str2都是引用数据类型,但是String不可被修改,所以str = "你好!" 和 str2 = new String("你好!") 都是创建一个新的对象,所以不会影响到原变量。

执行结果:

ii: 10
map: {"key":"world"}
str: Hello
str2: Hello

图解执行change方法前后如下图:

posted @ 2021-06-02 15:42  哲雪君!  阅读(1150)  评论(0编辑  收藏  举报