美文网首页ziJava学习笔记
java基础——String

java基础——String

作者: 陈晨_Fly | 来源:发表于2016-12-05 23:07 被阅读66次

    特性

    不可变类:所谓的不可变类是指这个类的实例一旦创建完成后,就不能改变其成员变量值。以下几点保证了String的不可变性:

    • String类被final修饰,不可继承
    • 内部所有成员都设置为私有变量且不存在value的set方法
    • 获取value时不是直接返回对象引用,而是返回对象的copy

    成员变量

    private final char value[];
    private final int offset;
    private final int count;
    

    其中,value存放具体字符串,offset表示偏移量,count表示char的数量。同时注意到,三者均为final修饰,根据java中final的要求所修饰变量要么在声明时候初始化,要么在构造函数中初始化。

    常量池

    jvm虚拟机为每个被装载的类型维护一个常量池。常量池就是该类型所用到常量的一个有序集合,包括直接常量(string,integer和 floating point常量)和对其他类型,字段和方法的符号引用。

    对于String常量,它的值是在常量池中的。而JVM中的常量池在内存当中是以表的形式存在的, 对于String类型,有一张固定长度CONSTANT_String_info表用来存储文字字符串值,注意:该表只存储文字字符串值,不存储符号引用。常量池中保存着很多String对象; 并且可以被共享使用,因此它提高了效率。
    字符串常量池优势:

    • 节省内存空间:常量池中所有相同的字符串常量被合并,只占用一个空间。
    • 节省运行时间:比较字符串时,==比equals()快。对于两个引用变量,只用==判断引用是否相等,也就可以判断实际值是否相等。
      分析如下代码:
    // str1指向在常量池中生成一个字符串123
    String str1 = "123";
    // str2通过new的形式指向了堆中生成的字符串,常量池中已经有123
    String str2 = new String("123");
    // str3在常量池和堆中各生成一个字符串,自身指向堆中数据
    String str3 = new String("456");
    

    常见问题

    String s1 = new String(“xyz”); 创建了几个对象?

    • 类加载对一个类只会进行一次。”xyz”在类加载时就已经创建并驻留了(如果该类被加载之前已经有”xyz”字符串被驻留过则不需要重复创建用于驻留的”xyz”实例)。驻留的字符串是放在全局共享的字符串常量池中的。
    • 在这段代码后续被运行的时候,”xyz”字面量对应的String实例已经固定了,不会再被重复创建。所以这段代码将常量池中的对象复制一份放到heap中,并且把heap中的这个对象的引用交给s1 持有。
    • 所以创建2个对象

    String真的不能修改吗?
    可以用反射完成String修改,参考如下demo:

    Field valueField = String.class.getDeclaredField("value");
    valueField.setAccessible(true);
    char[] value = (char[]) valueField.get(s);
    value[5] = '_';
    

    java.lang.String.intern()本质

    • String的intern()方法会查找在常量池中是否存在一份equal相等的字符串,如果有则返回该字符串的引用,如果没有则添加自己的字符串进入常量池。

    相关文章

      网友评论

        本文标题:java基础——String

        本文链接:https://www.haomeiwen.com/subject/qaylmttx.html