01 字符串优化处理

1.针对常量池的优化

针对常量池的优化是指: 当String对象拥有相同的值时,他们只引用常量池中的同一个拷贝.

public static void main(String[] args) {
    String str1 = "abc";
    String str2 = "ab" + "c";
    String str3 = new String("abc");

    System.out.println(str1==str2);
    System.out.println(str1==str3);
    System.out.println(str1==str3.intern());
}

true
false
true

以上代码显示str1 和str2引用了相同的地址,str3另开辟了新内地址; 参考图1,可以看出str1和str3在常量池中的位置是一样的,intern()方法返回是字符串对象在常量池中的引用.

String内存分配方式

图1 String内存分配方式

查看String.intern()源码,如下:

/**
 * Returns a canonical representation for the string object.
 * <p>
 * A pool of strings, initially empty, is maintained privately by the
 * class {@code String}.
 * <p>
 * When the intern method is invoked, if the pool already contains a
 * string equal to this {@code String} object as determined by
 * the {@link #equals(Object)} method, then the string from the pool is
 * returned. Otherwise, this {@code String} object is added to the
 * pool and a reference to this {@code String} object is returned.
 * <p>
 * It follows that for any two strings {@code s} and {@code t},
 * {@code s.intern() == t.intern()} is {@code true}
 * if and only if {@code s.equals(t)} is {@code true}.
 * <p>
 * All literal strings and string-valued constant expressions are
 * interned. String literals are defined in section 3.10.5 of the
 * <cite>The Java&trade; Language Specification</cite>.
 *
 * @return  a string that has the same contents as this string, but is
 *          guaranteed to be from a pool of unique strings.
 */
public native String intern();

上面是jdk源码中对intern方法的详细解释。
简单来说就是intern用来返回常量池中的某字符串,如果常量池中已经存在该字符串,则直接返回常量池中该对象的引用。
否则,在常量池中加入该对象,然后 返回引用。

2.subString()方法的内存泄露(JDK1.6)

subString()在jdk1.6中的源码如下:

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);
    }
}

// Package private constructor which shares value array for speed.
//包作用域的构造函数,目的是高效快速的 String 内的 char 数组对象
String(int offset, int count, char value[]) {
this.value = value;
this.offset = offset;
this.count = count;
}

通过上面代码可知,调用subString()方法,子字符串会复制整个String对象,然后做截取操作; 如果String对象本身比较大,重复做subString()操作,就会占据很大的内存.
虽然提高了运算速率,但是牺牲了内存空间(空间换时间).

再来观察下jdk1.7及以上版本中subString()方法源码:

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

public String(char value[], int offset, int count) {
    if (offset < 0) {
        throw new StringIndexOutOfBoundsException(offset);
    }
    if (count < 0) {
        throw new StringIndexOutOfBoundsException(count);
    }
    // Note: offset or count might be near -1>>>1.
    if (offset > value.length - count) {
        throw new StringIndexOutOfBoundsException(offset + count);
    }
    this.value = Arrays.copyOfRange(value, offset, offset+count);
}

public static char[] copyOfRange(char[] original, int from, int to) {
    int newLength = to - from;
    if (newLength < 0)
        throw new IllegalArgumentException(from + " > " + to);
    char[] copy = new char[newLength];
    System.arraycopy(original, from, copy, 0,
                     Math.min(original.length - from, newLength));
    return copy;
}

public static native void arraycopy(Object src,  int  srcPos,
                                        Object dest, int destPos,
                                        int length);

通过native的arraycopy复制了一份指定位置和长度的char数组.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值