乐趣区

关于java:全网最硬核的源码分析之String源码分析

String 类在日常开发过程中应用频率十分高,然而大家真的认真理解过它么。

基于 jdk1.8

一:实现接口。

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
  • String 类被 final 关键字润饰,不能被继承,创立后不可批改。
  • java.io.Serializable

能够实现序列化,标记接口,用于标识序列化,未实现该接口无奈被序列化。

  • Comparable<String>

能够比拟大小,这个接口只有一个 compareTo(T 0)接口,用于对两个实例化对象比拟大小。

  • CharSequence

String 实质是个 char 类型数组,这个接口是一个只读的字符序列。String、StringBuilder、StringBuffer 都实现了这个接口。

二:成员变量

/** The value is used for character storage. */
private final char value[];

/** Cache the hash code for the string */
private int hash; // Default to 0

能够看到,value[]是存储 String 的内容的,即当应用 String str = “abc”; 的时候,实质上,”abc” 是存储在一个 char 类型的数组中的。

三:实现办法

再持续看 String 类的一些办法实现:

 */
    public String substring(int beginIndex, int endIndex) {if (beginIndex < 0) {throw new StringIndexOutOfBoundsException(beginIndex);
        }
        if (endIndex > value.length) {throw new StringIndexOutOfBoundsException(endIndex);
        }
        int subLen = endIndex - beginIndex;
        if (subLen < 0) {throw new StringIndexOutOfBoundsException(subLen);
        }
        return ((beginIndex == 0) && (endIndex == value.length)) ? this
                : new String(value, beginIndex, subLen);
    }

public String concat(String str) {int otherLen = str.length();
        if (otherLen == 0) {return this;}
        int len = value.length;
        char buf[] = Arrays.copyOf(value, len + otherLen);
        str.getChars(buf, len);
        return new String(buf, true);
    }

public String replace(char oldChar, char newChar) {if (oldChar != newChar) {
            int len = value.length;
            int i = -1;
            char[] val = value; /* avoid getfield opcode */

            while (++i < len) {if (val[i] == oldChar) {break;}
            }
            if (i < len) {char buf[] = new char[len];
                for (int j = 0; j < i; j++) {buf[j] = val[j];
                }
                while (i < len) {char c = val[i];
                    buf[i] = (c == oldChar) ? newChar : c;
                    i++;
                }
                return new String(buf, true);
            }
        }
        return this;
    }

从下面的三个办法能够看出,无论是 substring、concat 还是 replace 操作都不是在原有的字符串上进行的,而是从新生成了一个新的字符串对象。说进行这些操作后,最原始的字符串并没有被扭转。

String 对象一旦被创立就是固定不变的,对 String 对象的任何扭转都不影响到原对象,相干的任何操作都会生成新的对象。

四、总结

1.String 类初始化后是不可变的(immutable)

String 应用 private final char value[]来实现字符串的存储,也就是说 String 对象创立之后,就不能再批改此对象中存储的字符串内容,就是因为如此,才说 String 类型是不可变的 (immutable)。程序员不能对已有的不可变对象进行批改。咱们本人也能够创立不可变对象,只有在接口中不提供批改数据的办法就能够。
然而,String 类对象的确有编辑字符串的性能,比方 replace()。这些编辑性能是通过创立一个新的对象来实现的,而不是对原有对象进行批改。比方:

s = s.replace("World", "Universe");

上面对 s.replace()的调用将创立一个新的字符串 ”Hello Universe!”,并返回该对象的援用。通过赋值,援用 s 将指向该新的字符串。如果没有其余援用指向原有字符串 ”Hello World!”,原字符串对象将被垃圾回收。

五 举荐浏览

全网最硬核的源码剖析之——String 源码剖析

Spring Boot 自动化配置原理带图全面解说

MySQL 3 大日志的作用

全网最硬核的源码剖析之——ArrayList 源码剖析

如果感觉对您有帮忙,心愿大家可关注一下,点个赞再走,感谢您的浏览。

退出移动版