深入理解java基础 -- 关于字符串String

String是final的,它是一个不可变对象,这一点可以从它的类的声明看出,它实现了serializable和comparable,保证了它可序列化和比较性,CharSequence是一个接口,表示char值的一个可读序列。此接口对许多不同种类的char序列提供统一的自读访问。此接口不修改该equals和hashCode方法的常规协定,因此,通常未定义比较实现 CharSequence 的两个对象的结果。他有几个实现类:CharBuffer、String、StringBuffer、StringBuilder。

public final class String implements java.io.Serializable, Comparable, CharSequence

关于String和new String

String是一个唯一可以不用new就可以产生一个对象的途径,像CharSequence是不能用字符串去生成的,必须要new,String在这一点上改进了,声明一个字符串String a = "abcd"和new String()的区别是:"abcd"这种形式的字符串,在JVM内部发生字符串拘留,即当声明这样的一个字符串后,JVM会在常量池中先查找有有没有一个值为"abcd"的对象,如果有,就会把它赋给当前引用.即原来那个引用和现在这个引用指点向了同一对象,如果没有,则在常量池中新创建一个"abcd",下一次如果有String s1 = "abcd";又会将s1指向"abcd"这个对象,即以这形式声明的字符串,只要值相等,任何多个引用都指向同一对象,如果是new String的话,就是不管内存里有没有这个对象都会新建一个新的对象来保存。所以newString的对象是不一样的,在比较的时候如果用==的话是返回false的。

记住一点:栈区存引用和基本类型,不能存对象,而堆区存对象。==是比较地址,equals()比较对象内容。

关于equals

public boolean equals(Object anObject) {

    这里的含义我理解为如果地址相同就返回true

    if (this == anObject) {

        return true;

    }

    equals和==区别就是多了这一步判断,这里把字符串转为char类型循环比较内容,所以equals比较的是值,会返回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;

}

注:基本类型是没有equals方法的,都在包装类型里面,覆盖了Object的equals,各自有不同的实现。

关于String的+号的实现

String对象是不可变的,所以为String对象重载的+号操作符就会带来一定的效率问题,比如一个简单的字符串连接也许就会生成大量的对象,造成垃圾回收的效率变低,所以jvm在实现String的操作的时候,会把java文件编译成字节码文件,在java编程思想里有提到,+号操作的编译会自动引入StringBuilder类,然后对每个字符串调用的append方法,这样实现了+好操作,使操作更高效。所以,编译器为String自动优化了性能。但是它也会每次循环的时候都会new 一个StringBuilder的对象,这样的话还不能完全信任String的+,所以在循环操作比较多的时候还是要选择StringBuilder。

关于subString

subString是String截取字符串的一个方法,它并不是真的把字符串截取了,而是生成了一个新的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);

}

它调用了String中三个参数的方法,使用了Arrays.copyOfRange获取char。

猜你喜欢

转载自blog.csdn.net/u011877409/article/details/80300046