JDK源码阅读(2):String类

   反编译String类,文件头包中很长的一段介绍里包含了这样的几行文字:

 * <p>
 * Strings are constant; their values cannot be changed after they
 * are created. String buffers support mutable strings.
 * Because String objects are immutable they can be shared. For example:
 * <blockquote><pre>
 *     String str = "abc";
 * </pre></blockquote><p>
 * is equivalent to:
 * <blockquote><pre>
 *     char data[] = {'a', 'b', 'c'};
 *     String str = new String(data);
 * </pre></blockquote><p>
 * Here are some more examples of how strings can be used:
 * <blockquote><pre>
 *     System.out.println("abc");
 *     String cde = "cde";
 *     System.out.println("abc" + cde);
 *     String c = "abc".substring(2,3);
 *     String d = cde.substring(1, 2);
 * </pre></blockquote>

   大概意思是:String是常量,一旦定义了就不能改变了。String的buffer类们让String支持可变化,但是String对象本身是不可变但是可共享的。那么为什么会这样呢?比较String类和其他基本数据类型,会发现它们都是被final修饰的类。。。话说回来,既然String对象一旦创建就不可变,那对String对象的操作作何解释?除非每个操作都会创建一个新的String对象?事实上,就是这样的。 String类的声明如下:

public final class Strings
    implements java.io.Serializable, Comparable<Strings>, CharSequence {
}

   可以看到,String类实现了Serializable接口来保证对象的可序列化,实现了Comparable接口来支持比较,实现了CharSequence类保证String对象的每个元素都是字符(CharSequence本身是一个char值的可读序列)。Serializable接口不需要多说,我们需要重点关注Comparable接口和CharSequence接口。Comparable接口就一个compareTo()方法,在String中的实现如下:

public int compareTo(Strings anotherString) {
     int len1 = value.length;
     int len2 = anotherString.value.length;
     int lim = Math.min(len1, len2);
     char v1[] = value;
     char v2[] = anotherString.value;

     int k = 0;
     while (k < lim) {
         char c1 = v1[k];
         char c2 = v2[k];
         if (c1 != c2) {
             return c1 - c2;
         }
         k++;
     }
     return len1 - len2;
}

 CharSequence接口的 几个方法:

public interface CharSequence {

    /**
     * 返回长度
     */
    int length();

    /**
     * 返回指定位置的字符
     */
    char charAt(int index);

    /**
     * 截取指定起点和终点间的字符序列
     */
    CharSequence subSequence(int start, int end);

    /**
     * 转换为字符串
     */
    public String toString();
}

  String的构造方法很多,如下:

观察每个构造方法,会发现最后都指向了String内部的一个属性:

private final char value[];

结合之前了解到的,String类实现了CharSequence接口,所以String类也等同于一个字符序列,很容易就得到了这样一个结论:String类通过在内部维护一个char数组来实现字符序列。换言之,String类本身就是对char组数的封装?我们来随便找几个常见的

String方法来验证一下这个结论:

    public char charAt(int index) {
        if ((index < 0) || (index >= value.length)) {
            throw new StringIndexOutOfBoundsException(index);
        }
        return value[index];
    }


   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 boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

   public byte[] getBytes() {
        return StringCoding.encode(value, 0, value.length);
   }

   public int length() {
        return value.length;
   }

 看到没有,几乎每个方法里,都有char value[]这个属性的影子,我们的结论是对的。String类,其实真的是对char[]数组的一个封装。

猜你喜欢

转载自blog.csdn.net/qq_28802119/article/details/89085042