==
String类型是个引用类型,所以对于字符串类型而言==操作符比较的就是引用。考虑下面的代码
String str1 = "abd";
String str2 = "abd";
System.out.println(str1 == str2);
这里会返回true还是false?答案是true。str1和str2是常量池中同一个字符串的引用。如果在编译时期就能够确定值的字符串常量并且字面值相同的话,那么引用也是相同的。我个人觉得对于字符串能用equals就别用==了,一定要用==的应用场景应该不会很多。
String是个不可变类。
String类是一个不可变类,关于不可变类的讨论《Effective Java》中第十五条“使可变性最小化”讨论的很好。看下面的代码:
String str = "abfde";
str.replace('f', 'c');
System.out.println(str);
这时候会输出什么?输出的还是"abfde"。因为String是个不可变类,所以replace并不能改变str的值,想要达到预期的效果应该是这样的:str = str.replace('f', 'c');
字符串的拼接与分割
上面提到了字符串是个不可变类,所以就要注意用+操作符拼接两个字符串的操作了。每次运算结果都要生成一个新的字符串,这样对性能会造成很大的影响。所以Java中才会有StringBuilder和StringBuffer这两个类。JVM能够对单行的字符串连接操作用StringBuilder进行优化,但是对于多行的和循环体内的字符串连接操作这样简单的优化依然会创建很多冗余的StringBuiler对象,所以要自己手动的去写。StringBuffer和StringBuilder有什么区别呢?StringBuffer是线程安全的,StringBuilder是线程不安全的。那是不是StringBuffer更好呢?并不是,StringBuffer在类的内部进行了同步,然而它的应用场景绝大多数是在单线程的环境下,所以这个同步反而影响了性能。我更喜欢StringBuilder点吧,线程安全的时候性能更好,需要同步的时候可以在外部进行同步。对于split方法,split会将传入的字符串编译成一个Pattern对象。如果在一个大量循环的循环体中使用split,每次循环都会创建一个Pattern对象,这会影响程序的性能。这时候可以自己用Pattern去做分割操作,这样只会有一个Pattern对象。还要注意java1.7以下的subString方法,subString不会生成新的字符串,原字符串依然会再内存中。所以当大量的进行这样的操作的时候会产生内存泄露,典型的占而不用。当然,1.7之后的版本就没有这样的问题了。
说个和题目无关的,记得以前读《Pointers On C》的时候关于for循环有这样两个建议:
-
在一些场景下可以使用
!=
进行条件判断,比如:for(int i = 0; i != 100; ++i){ //和 i < 100是一样的 }
用
++i
而不是i++
这样做的好处是什么呢?好处就是提高性能。具体看书吧,我也记不住了0.0。