String

发布于:2022-08-08 ⋅ 阅读:(308) ⋅ 点赞:(0)

String 为什么不可变

java.lang.String 源码
字符串的本质是一个byte[] 的字节数组(jdk 11),在jdk8中是一个字符数组

public final class String implements Serializable, Comparable<String>, CharSequence {
    @Stable
    private final byte[] value;// 字符串本质
    private final byte coder;
    private int hash;
    private static final long serialVersionUID = -6849794470754667710L;
    static final boolean COMPACT_STRINGS = true;
    private static final ObjectStreamField[] serialPersistentFields = new ObjectStreamField[0];
    public static final Comparator<String> CASE_INSENSITIVE_ORDER = new String.CaseInsensitiveComparator();
    static final byte LATIN1 = 0;
    static final byte UTF16 = 1;
}

由此可见在java语言中String是一个final关键字修饰的类,该类不可以具有子类,不可以修改。注意String是一个引用型类,不是基本数据类型。基本数据类型只有一下8个byte,short,int,float,double,long,char,boolean,与此相对应的是其8大包装类类型

在这里插入图片描述
注意所谓的字符串不可变,指的是字符串的内容不可变,而不是字符串的引用不能变
1、由于字符串使用范围广,防止SQL注入等,保证安全
2、多线程中,只有不变的对象和值是线程安全的,可以在多个线程中共享数据。
3、由于字符串 hashcode 属性不会变更,保证了唯一性,使得类似 HashMap,HashSet 等容器才能实现相应的缓存功能。由于 String 的不可变,避免重复计算 hashcode,只要使用缓存的 hashcode 即可,这样一来大大提高了在散列集合中使用 String 对象的性能。
4、当字符串不可变时,常量池才具有意义,减少了重复的,相同字面量的字符串,共享内存,节省堆内存空间,

String 的创建

        String s1 = "hello";
        String s2 = new String("hello");
        char[] ch = new char[]{'h','e','l','l','o'};
        String s3 = new String(ch);
        String s4 = String.valueOf(10);

字符串的字面量就是一个字符串对象
s1方式创建的字符串,查询堆中是否存在,如果不存在就产生一个对象,开辟一个常量池,将其存储,后续使用直接去常量池中取字符串。
String对象一旦被创建就是固定不变的了,对String对象的任何改变都不影响到原对象,相关的任何修改操作都会生成新的对象.
每当我们创建字符串常量时,JVM会首先检查字符串常量池,如果该
字符串已经存在常量池中,那么就直接返回常量池中的实例引用。如果字符串不存在常量池中,就会实例化该字符串并且将其放到常量池中。由于String字符串的不可变性。因此常量池中一定不存在两个相同的字符串
字符串对象的手动入池

    public native String intern();

调用intern方法会将当前字符串引用指向的对象保存到字符串常量池中,有两种情况:
1.若当前常量池中已经存在了该对象,则不再产生新的对象,返回常量池中的String对象
2.若当前常量池中不存在该对象,则将该对象入池,返回入池后的地址。

        String s1 = "hello";
        String s2 = new String("hello");
        System.out.println(s1 == s2);
        s2 = s2.intern();
        System.out.println(s1 == s2);

第一次输入false,第二次输出true,注意手动入池方法具有返回值,需要替换原先对象,即是入池成功

常量池

两种形态:静态常量池和运行时常量池。
静态常量池,即*.class文件中的常量池,class文件中的常量池不仅仅包含字符串(数字)。字面量,还包含类、方法的信息,占用class文件绝大部分空间。
运行时常量池,则是jvm虚拟机在完成类装载操作后,将class文件中的常量池载入到内存中,并保存在方法区中,我们常说的常量池,就是指方法区中的运行时常量池。

字符串池的优点

避免了相同内容的字符串的创建,节省了内存,省去了创建相同字符串的时间,同时提升了性能;
字符串池的缺点
牺牲了JVM在常量池中遍历对象所需要的时间


网站公告

今日签到

点亮在社区的每一天
去签到