GO-BACK

String、StringBuffer 、StringBuilder

String

  • String 是字符串对象常量、对象一旦创建之后该对象的值不可更改:String s=”abce”是一种非常特殊的形式,和new 有本质的区别。它是java中唯一不需要new 就可以产生对象的途径

  • StringBuilder、StringBuffer 对象是变量的、其对象可以更改或者是说其对应的值是可以更改的

    1 String str="abc";
    2 System.out.println(str);
    3 str=str+"de";
    4 System.out.println(str);
    
  • 如果运行这段代码会发现先输出“abc”,然后又输出“abcde”,好像是str这个对象被更改了,其实,这只是一种假象罢了,JVM对于这几行代码是这样处理的,首先创建一个String对象str,并把“abc”赋值给str,然后在第三行中,其实JVM又创建了一个新的对象也名为str,然后再把原来的str的值和“de”加起来再赋值给新的str,而原来的str就会被JVM的垃圾回收机制(GC)给回收掉了,所以,str实际上并没有被更改,也就是前面说的String对象一旦创建之后就不可更改了。所以,Java中对String对象进行的操作实际上是一个不断创建新的对象并且将旧的对象回收的一个过程,所以执行速度很慢

  • String实现继承-最后到内部存储都是以char[]str来存储对应的文本内容

    public final class String implements java.io.Serializable, Comparable<String>, CharSequence
    
  • StringBuffer 实现继承-CharSequence(有序队列char)

    public final class StringBuffer extends AbstractStringBuilder implements java.io.Serializable, CharSequence
    
    .....
    //String方法    
    @Override
    public synchronized StringBuffer append(String str) {
        toStringCache = null;
        super.append(str);
        return this;
    }
    
  • 其append方法都有synchronized 标志、顾当有多个线程调用相同对象进行添加时、其线程是安全的

  • toString():也验证了String内部存储转换:value:char[]

       @Override
    public synchronized String toString() {
        if (toStringCache == null) {
        toStringCache = Arrays.copyOfRange(value, 0, count);
        }
        return new String(toStringCache, 0, count);
        }
    
  • StringBuilder -继承

    public final class StringBuilder extends AbstractStringBuilder implements java.io.Serializable, CharSequence
    
    ....
    //方法--线程不安全的
     @Override
    public StringBuilder append(String str) {
        super.append(str);
        return this;
    }
    
  • class 用final修饰、代表其无法实现被继承

equals、==

  • ==:== 比较的是变量(栈)内存中存放的对象的(堆)内存地址,用来判断两个对象的地址是否相同,即是否是指相同一个对象。比较的是真正意义上的指针操作。
  • 1、比较的是操作符两端的操作数是否是同一个对象。
    2、两边的操作数必须是同一类型的(可以是父子类之间)才能编译通过。
    3、比较的是地址,如果是具体的阿拉伯数字的比较,值相等则为true,如:
    int a=10 与 long b=10L 与 double c=10.0都是相同的(为true),因为他们都指向地址为10的堆。

其实直接对应数值的比对也是进行地址的比对-地址指向的都是常量为10的堆地址

  •   equals用来比较的是两个对象的内容是否相等,由于所有的类都是继承自java.lang.Object类的,所以适用于所有对象,如果没有对该方法进行覆盖的话,调用的仍然是Object类中的方法,而Object中的equals方法返回的却是==的判断。

    //Object内部equals方法:其实内部就是进行的==判断、也就是地址指针的判断
      public boolean equals(Object obj) {
            return (this == obj);
        }
    
    //String内部的equals--先比较对象地址、然后比较长度、然后比较内部的char[]的数值
    
    public boolean equals(Object anObject) {
        if (this == anObject) {
        return true;
        }
        if (anObject instanceof String) {
        String anotherString = (String) anObject;
        int n = length();
        if (n == anotherString.length()) {
            int i = 0;
            while (n-- != 0) {
                if (charAt(i) != anotherString.charAt(i))
                        return false;
                i++;
            }
            return true;
            }
        }
        return false;
    }
    
  • 经典案例

picture

  • 参考文献

equals和==的区别小结

Java中的String,StringBuilder,StringBuffer三者的区别