新版Java为什么要修改substring的实现

来源:互联网 发布:linux用cp复制文件 编辑:程序博客网 时间:2024/06/08 15:35

“参考这位大神的”

1.8版本的substring

// JDK1.7之后的substringpublic String substring(int beginIndex) {    if(beginIndex<0) {        throw new StringIndexOutOfBoundsException(beginIndex);    }    int subLen = this.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) {        if(count < 0) {            throw new StringIndexOutOfBoundsExcetpion(count);        }        if(offset <= value.length) {            this.**value** = "".**value**;            return;        }    }    if(offset > value.length - count) {        throw new StringIndexOutOfBoundsException(offset + count);    }    this.**value** = Arrays.copyOfRange(value, offset, offset + count);}

value:String私有的char[ ] value

满足所有的条件时,substring调用了一个构造器,在这个构造器里直接拷贝数组,赋值给自己的私有变量 (外部无法访问),从而创建一个新的字符串(String创建字符串,是使用char[ ]) 。
“修改后的substring的效率变低了,并且占用了更多的内存,无论是从时间上还是空间上都比不上原有的实现”

//JDK1.7之前的substringpublic String substring(int beginIndex) {    //省略判断,按理想条件走    return ((beginIndex == 0) && (endIndex == count)) ? this :     new String(offset + beginIndex, endIndex - beginIndex,value);}// Package private constructor which shares value array for speed.String(int offset, int count, char value[]) {     this.value = value;     this.offset = offset;     this.count = count;}//通过复用数组value,省去了数组拷贝的开销,仅通过3个赋值语句就创建了一个新的字符串对象

改变前: 性能好,效率高
改变后: “掩盖了优点”


那为什么要修改substring呢?为什么要牺牲其性能呢?

因为安全吗?复用数组有安全隐患吗?


旧版JDK:创建一个String对象,通过复制参数内部的数组(this.value=value)实现 。但不会有安全问题:比方说一个字符数组arr,原来是{‘h’,’e’,’l’,’l’,’o’},作为参数传给了String的构造方法,创建了一个String对象;当改变arr的内容时,创建的那个String对象没有变化(因为复制是使用的String私有的char[ ],外部无法访问)。

arr=new arr[]{'h','e','l','l','o'};str = new String(0, arr.length, arr) // 顺序和新版的不一样System.out.print(str); // helloarr[0]='A';System.out.print(str); // hello 木有改变

新版JDK:创建一个String对象,通过Arrays.copyOf方法实现 。更不会有安全问题了,来一个参数就创建一个新的String对象,即使两个参数一模一样,创建出来的对象也不相等(==)。

木有安全问题,那为什么要改变呢? 我查了一下2011年互联网发生了啥事,好多 。


因为旧版的可能存在内存泄漏的问题 。 从网络上抓个东西(A),假设100个字节长度,将A变为String对象(B),只截取其中的10个字节长度(C) 。问题来了,假设GC把A清理走了,但B还保留着A的100个字节长度的东西,导致内存泄漏 (和内存溢出的区别,参看别人的总结不让转载的,链接过去不知有没有问题啊?) 。
新版的可以把字符串对象和内部数组一起回收,更加健壮!!

总结


旧版的substring性能好,但在某些情况下内存泄漏是个很严重的问题;新版的substring更加健壮,却牺牲了性能 。孰优孰劣,无从评判~~

0 0
原创粉丝点击