首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

深入【Java】底层细节知识点(3)String类的深入理解

深入【Java】底层细节知识点(3)String类的深入理解

S
tring


了解一个类最好的方式就是看源码
public final class String    implements java.io.Serializable, Comparable<String>, CharSequence{    /** The value is used for character storage. */    private final char value[];    /** The offset is the first index of the storage that is used. */    private final int offset;    /** The count is the number of characters in the String. */    private final int count;    /** Cache the hash code for the string */    private int hash; // Default to 0    /** use serialVersionUID from JDK 1.0.2 for interoperability */    private static final long serialVersionUID = -6849794470754667710L;    public String substring(int beginIndex, int endIndex) {    if (beginIndex < 0) {        throw new StringIndexOutOfBoundsException(beginIndex);    }    if (endIndex > count) {        throw new StringIndexOutOfBoundsException(endIndex);    }    if (beginIndex > endIndex) {        throw new StringIndexOutOfBoundsException(endIndex - beginIndex);    }    return ((beginIndex == 0) && (endIndex == count)) ? this :        new String(offset + beginIndex, endIndex - beginIndex, value);}public String concat(String str) {    int otherLen = str.length();    if (otherLen == 0) {        return this;    }    char buf[] = new char[count + otherLen];    getChars(0, count, buf, 0);    str.getChars(0, otherLen, buf, count);    return new String(0, count + otherLen, buf);}public String replace(char oldChar, char newChar) {    if (oldChar != newChar) {        int len = count;        int i = -1;        char[] val = value; /* avoid getfield opcode */        int off = offset;   /* avoid getfield opcode */        while (++i < len) {        if (val[off + i] == oldChar) {            break;        }        }        if (i < len) {        char buf[] = new char[len];        for (int j = 0 ; j < i ; j++) {            buf[j] = val[off+j];        }        while (i < len) {            char c = val[off + i];            buf = (c == oldChar) ? newChar : c;            i++;        }        return new String(0, len, buf);        }    }    return this;}} 更多的不再展示。
从以上的源码中获得信息:
  • String是final类,这意味着,这个类不能被继承,也不可有子类,其中的方法默认都是final方法
  • String类是通过char数组来保存字符串的
  • String类对字符串的操作都是对新字符串操作。S
    tring


字符串常量池:
  • 每当我们创建字符串常量时,JVM会首先检查字符串常量池,如果该字符串已经存在常量池中,那么就直接返回常量池中的实例引用。如果字符串不存在常量池中,就会实例化该字符串并且将其放到常量池中。由于String字符串不可变,所以常量池中一定不存在两个相同的字符串
  • 静态常量池和运行时常量池
    • 静态常量池,即.class文件中的常量池,class文件中的常量池不仅仅包含字符串(数字)字面量,还包含类、方法的信息,占用class文件绝大部分空间。
    • 运行时常量池,则是jvm虚拟机在完成类装载操作后,将class文件中的常量池载入到内存中,并保存在方法区中,我们常说的常量池,就是指方法区中的运行时常量池。

    虽说,字符串的比较,我们使用equals方法,但用==号就可以看出,a和b指向的同一个对象。而new以后就产生新的对象。
    如果使用equals比较三者,得出的结果,肯定都是true

    由于c是new出来的,所以产生了两个对象,一个是栈区中的c,另一个就是堆中的123,他们的引用关系是c->123->123(常量池中的)
    也就是说,尽管c是创建在堆中,但其value还是常量池中的123
    当我们对字符串,进行拼接,替换等操作时,会创建一个新的对象来操作,之后旧的对象,就会被当作垃圾回收。
返回列表