【Java源码】String类

一、属性解读

/** 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
1、String中使用字符数组value[]保存内容,由修饰final可知String一旦被赋值,它的内容就不能改变,这是String和StringBuilder、StringBuffer的主要区别;之前我以为是因为final修饰了String类造成了String不可变,这是错误的,final修饰类只是使类变成不可继承。由于value是不可变的,多个String对象可能会共享一个value中的值。

2、offset表示String对象的内容的起始字符在value[]中的偏移,因为多个对象可能公用一个value,所以有的对象可能只用了value的一部分字符。

比如:对于substring函数,就会直接将原串的value赋给子串,而只是变更子串的offset和count

 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);//子串的offset和count变更
    }
String(int offset, int count, char value[]) {
	this.value = value;
	this.offset = offset;
	this.count = count;
    }

又如,String(new StringBuilder(“xx").toString());

public String(StringBuilder builder) {
        String result = builder.toString();
        this.value = result.value;
        this.count = result.count;
        this.offset = result.offset;
    }


3、count表示String对象的内容中字符的个数,它并不是指value[]的长度。所以,用count来判断对象内容是否为空或取长度。

public boolean isEmpty() {
	return count == 0;
    }
public int length() {
        return count;
    }
4、hash存储String对象的hashCode
 public int hashCode() {
	int h = hash;
	if (h == 0) {
	    int off = offset;//String的offset位置是对象第一个字符在value[]中的偏移
	    char val[] = value;
	    int len = count;

            for (int i = 0; i < len; i++) {
                h = 31*h + val[off++];//挨个将字符取出进行hash,这样相同字符串的hashCode肯定是一样的
            }
            hash = h;
        }
        return h;
    }
对于equals方法,先比较对象的引用再比较字符
 public boolean equals(Object anObject) {
	if (this == anObject) {
	    return true;
	}
	if (anObject instanceof String) {
	    String anotherString = (String)anObject;
	    int n = count;
	    if (n == anotherString.count) {
		char v1[] = value;
		char v2[] = anotherString.value;
		int i = offset;
		int j = anotherString.offset;
		while (n-- != 0) {
		    if (v1[i++] != v2[j++])
			return false;
		}
		return true;
	    }
	}
	return false;
    }

二、String对象的产生

1、直接引用常量池字符

String s1 = "Hello"; //将引用指向位于方法区的常量池中的“Hello”
2、使用常量池字符串构造

String s2 = new String("Hello");//创建新的对象,并将常量池中的值赋给它,对应源码方法如下:
public String(String original) {
	int size = original.count;
	char[] originalValue = original.value;
	char[] v;
  	if (originalValue.length > size) {
 	    // The array representing the String is bigger than the new
 	    // String itself.  Perhaps this constructor is being called
 	    // in order to trim the baggage, so make a copy of the array.
            int off = original.offset;
            v = Arrays.copyOfRange(originalValue, off, off+size);
 	} else {//其实,若这个字符串在内存中是一个完整的char[],即不是某个value[]的一部分,则不需要赋值产生新的char[]
 	    // The array representing the String is the same
 	    // size as the String, so no point in making a copy.
	    v = originalValue;
 	}
	this.offset = 0;
	this.count = size;
	this.value = v;
    }
3、通过加号+产生字符串

3.1 常量字符的+

String s4 = "He" + "ll";//编译后为:String s4 = "Hell";
3.2 字符串对象+常量字符或字符串对象
String s5 = s1 + "XX";//编译后的代码为:String s5 = (new StringBuilder(String.valueOf(s1))).append("XX").toString();//实际产生了3个对象
3.2 常量字符串 + 常量字符或字符串对象

String s55 = "XX" + s1;//编译之后优化为(new StringBuilder("XX")).append(s1).toString();//产生了两个对象










  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,关于Java String的replace方法,其源码如下: ``` 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; } ``` 这个方法用于将字符串中的一个字符替换成另一个字符,并返回新的字符串。我们来逐行分析一下它的源码: 1. 如果要替换的字符和替换后的字符相同,则直接返回原字符串。 ``` if (oldChar != newChar) { ``` 2. 获取字符串的长度和字符数组。 ``` int len = value.length; char[] val = value; /* avoid getfield opcode */ ``` 3. 在字符数组中查找要替换的字符。 ``` int i = -1; while (++i < len) { if (val[i] == oldChar) { break; } } ``` 4. 如果找到了要替换的字符,则将其替换为新字符,否则直接返回原字符串。 ``` 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); } ``` 5. 如果要替换的字符不存在,则直接返回原字符串。 ``` return this; ``` 总体来说,这个方法的实现比较简单,就是遍历字符数组,找到要替换的字符,然后再将其替换成新字符,最后返回新的字符串。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值