String

对象

String并不是一个基本数据类型,而是一个对象,但是特殊的地方在于,String的问题在于每一次改变String的值的时候,就会重新在堆里生成一个String对象,所以一个对象作为参数,还是形参,比如当一个main方法调用另一个方法A给String重新赋值,是不会成功的,这就是因为在赋值的时候会重新在堆里生成了一个String对象,这样的话方法的栈帧中也只是改变引用的地址,随着方法A的调用结束,栈帧随之消失,main方法中的String对象仍然是引用的原来的String对象,并不会像其他的对象数据类型一样改变,如果要堆StringBuilder对象做上述操作的话,那么必须append,要不然的话只是把A方法中StringBuilder对象的引用地址变了,A方法执行完又没变。

问题

因为堆的内存并不是像栈一样随时清理的,所以String对象如果多次改变值,性能是非常差的,而且非常影响堆内存的使用。

String 可以字符串直接赋值,任何对象都有toString方法,这是来自于Object的,是所有类的父类。

比较

  1. public class StirngTest1 {
  2. public static void main(String[] args) {
  3. String a=new String("123");
  4. //先在堆中创建一个a对象再说,然后栈帧中保存a对象的地址,先去常量池中看有没有123,因为咱们后面这个b是有"123"的,所以再引用其地址过来
  5. //然后a保存的值是常量池中"123"的地址
  6. String b="123";//会直接在字符串常量池中创建 123这个字符串对象 然后将main方法栈帧中的b的值 赋一个常量池的地址值
  7. String c="123";//会直接在字符串常量池中创建 123这个字符串对象 然后将main方法栈帧中的c的值 赋一个常量池的地址值
  8. System.out.println(a==b); //所以此时比较栈帧中的引用地址值 a肯定不==b 因为就不是一个对象
  9. System.out.println(b==c); //b肯定是==c的
  10. System.out.println(a.equals(b));
  11. c=null;//将引用地址置为null
  12. System.out.println(c==null); //==比较是true
  13. // System.out.println(c.equals(null)); //equals找堆中的对象 找不到的 所以空指针
  14. String d="好好学习";//常量池"好好学习"地址
  15. String e="好好";//常量池“好好”地址
  16. String f="学习";//常量池“学习”地址
  17. String g=e+f; //先在堆里生成一个e 然后生成一个f 再相加 生成一个g 发现常量有对应的值 然后把常量池的地址拿过来赋给g在堆中的对象 然后g堆中的地址再赋给栈帧
  18. System.out.println(d==e+f);
  19. System.out.println(d.equals(e+f));
  20. System.out.println(d==g);
  21. System.out.println(d.equals(g));
  22. }
  23. }

StringBuilder

因为String不支持频繁修改的原因,所以诞生了StringBuilder,StringBuilder是一个实打实的正常的对象。

创建

需要new
StringBuilder stb=new StringBuilder("我是builder");

优点:

StringBuilder的好处在于对象赋值的时候,不会在堆里重新生成一个对象,然后修改栈的引用地址的,是直接在堆里的对象进行修改的,所以支持频繁修改,速度会提升很多,也不会占用堆内存。

缺点:

StringBuilder不支持线程安全

常用方法

append()

StringBuffer sb = new StringBuffer(“abc”);
sb.append(true);
则对象sb的值将变成”abctrue”。

deleteCharAt()

StringBuffer sb = new StringBuffer(“Test”);
sb. deleteCharAt(1);

insert方法

StringBuffer sb = new StringBuffer(“TestString”);
sb.insert(4,false);

reverse

StringBuffer sb = new StringBuffer(“abc”);
sb.reverse();

StringBuffer

StringBuilder的基础上支持线程安全,大部分方法上加上synchronize关键字实现的线程安全,所以StringBuffer相对StringBulider来讲,效率会降低一点。
构造方法

  • a) public StringBuffer()无参构造方法,初始化容量为16
  • b) public StringBuffer(int capacity)指定容量的字符串缓冲区对象
  • c) public StringBuffer(String str)指定字符串内容的字符串缓冲区对象,容量为字符串的长度+16

其他基本和Builder相同。