String
# 7. String
做成员变量(字段/属性/类变量)时,如果只写String str;那么默认赋值为null。
做局部变量(方法里的变量)时,如果只写String str;是不会默认赋值null的,这里仅声明了一个str变量, 在栈内存中有定义,但没有任何值,null其实也是一种值。此时任何调用str的操作,编译时就均会报错,是error, 不是异常。null的话,你屏幕输出(toString方法)的结果为字符串null,但其它调用str的操作,编译可通过, 运行时会空指针异常,此时是异常。
String str = ""; 这个跟"abc"、"中国",本质上这都一样,只是空串,长度为0罢了。 ""是空字符串,但是也是字符串,没有什么东西。而null是空的意思,什么都没有,没有地址。
if (str == null || str == "") {}//字符串判断空的写法
# String、String StringBuffer 和 StringBuilder 的区别是什么?
String是只读字符串,它并不是基本数据类型,而是一个对象。从底层源码来看是一个final类型的字符数组,所引用的字符串不能被改变,一经定义,无法再增删改。每次对String的操作都会生成新的String对象。
private final char value[];
每次+操作 : 隐式在堆上new了一个跟原字符串相同的StringBuilder对象,再调用append方法 拼接+后面的字符。
StringBuffer和StringBuilder他们两都继承了AbstractStringBuilder抽象类,从AbstractStringBuilder抽象类中我们可以看到
/**
* The value is used for character storage.
*/
char[] value;
2
3
4
他们的底层都是可变的字符数组,所以在进行频繁的字符串操作时,建议使用StringBuffer和StringBuilder来进行操作。 另外 StringBuffer 对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。StringBuilder 并没有对方法进行加同步锁,所以是非线程安全的。
# equals与==的区别
# ==
== 比较的是变量(栈)内存中存放的对象的(堆)内存地址,用来判断两个对象的地址是否相同,即是否是指相同一个对象。比较的是真正意义上的指针操作。
比较的是操作符两端的操作数是否是同一个对象。
两边的操作数必须是同一类型的(可以是父子类之间)才能编译通过。
比较的是地址,如果是具体的阿拉伯数字的比较,值相等则为true,如:
int a=10 与 long b=10L 与 double c=10.0都是相同的(为true),因为他们都指向地址为10的堆。
# equals
equals用来比较的是两个对象的内容是否相等,由于所有的类都是继承自java.lang.Object
类的,所以适用于所有对象,如果没有对该方法进行覆盖的话,调用的仍然是Object类中的方法,而Object中的 equals 方法返回的却是 == 的判断。
总结:
所有比较是否相等时,都是用equals 并且在对常量相比较时,把常量写在前面,因为 object 可能为 null 。推荐安装阿里插件来排查老代码使用“==”,替换成equals