String
String是一个被final修饰的类,直接继承于Object,同时也实现了charsequence接口,String被声明为final也就不可以被继承了。由于String的方法比较多,这就不一一的列出来说了。
在C/C++,String通常都用字符数组代替,不例外,由于JAVA是从C++发展来的,String内部其实也是一个char[],并且在JVM启动的时候,内部就已经维护了一个String池,也就是我们常说的字符串缓冲区,这里面的字符串不能重复,每个新来的成员都会被做比较,如果没有相同的则加进来,有相同的则不加。
下面看一下String的几种声明类型:
String s = new String("hello");
实际上这种声明方式简单明了的在堆上新建了一个String类型的对象,这个对象的内部指针指向一个hello 的值。
String s = "hello";
这种声明方式呢其实是一种静态的声明方式,现在String池里去寻找是否有一样的值,如果有的话直接拿过来用,没有的话会创建一个String对象。
String s = "he"+"llo";
这种声明方式是将两个字符串拼接起来。这种也是我们接下来需要讲到的问题。
我们说String是一个final的类。那么这样的话
String s = "he"+"llo"+"world";
实际上是在堆上声明了两个String对象,s为"he"+"llo"的返回结果,当执行+"world"的时候,又会声明一个对象,这个对象是“hello”+“world”的结果,当然,hello是会等着被GC回收的,那么问题来了,GC不是随时都在执行的,当堆满后就会触发GC,如果没满,那么GC也只能当大爷了,这样我们的程序效率就不是很高,众多的辣鸡对象不能被回收。
事实上执行这段语句的时候,被JVM隐式的创建了一个StringBuilder 的对象,实际上执行的是
StringBuilder sb = new StringBuilder();
sb.append("he");
sb.append("llo");
sb.append("world");
“为什么会这么做?”
当然是为了效率,StringBuilder在单个线程访问的时候相比StringBuffer是速度最快的,而且也能避免垃圾对象的问题。