通过专项练习,最终发现Java中和字符串有关的题目错的比较多。
对于这部分的内容掌握的不是很好,还有就是平时使用字符串的时候不会考虑的太多的细节。
而是直接使用,所以很少出错,比如一般都是这样使用String str = "Hello world";
而没有过多的在意它的细节。
如果忘记了字符串的实现细节,可以参考下面的文章,它将会帮助你对于字符串有更深入的了解。或者也可以做完题目之后再看参考文章,来检测自己是否完全掌握了字符串。
字符串知识回顾参看文章
下面是一些比较有代表性的字符串题目,可以做完之后再参考答案,如果可以做全队,说明字符串掌握的还不错。
a,b在常量池中,c,d是new出来的,在栈空间中且c,d的Hello那句在堆空间中,比较的时候,引用数据类型比地址基本数据类型比值,所以ab,c,d是new出来的地址不一样是false,equals重写了==,比较的是对象值,所以abcd任何两个用equals都true
最终答案选
ADE
string类重写equals方法后,先会判断c是否是string类型的实例,这里的c是char数组,所以返回false
最终答案是 :B
String a = “a”;
String b = “b”;
String str1 = “a” + “b”;//常量池中的对象
String str2 = a + b; //在堆上创建的新的对象
String str3 = “ab”;//常量池中的对象
System.out.println(str1 == str2);//false
System.out.println(str1 == str3);//true
System.out.println(str2 == str3);//false
最终答案:AD
答案参考链接
最终答案为A
java 中String是 final,也就是不可变,一旦初始化,其引用指向的内容是不可变的。
也就是说,String str = “aa”;str=“bb”;第二句不是改变“aa”所存储地址的内容,而是另外开辟了一个空间用来存储“bb”;同时由str指向原来的“aa”,现在已经不可达,GC时会自动回收。因此String作为参数传进来时候,str= “test ok”; 实际给副本引用str指向了新分配的地址,该地址存储“test ok”。
因此,原先的str仍然指向“good”
最终的答案:D
1.可变不可变
String用final修饰,所以string对象是不可变的
StringBuffer和StringBuilder都是继承AbstratStringBuilder,在AbstratStringBuilder中是使用字符串数组保存字符串,由此可知这两种对象是可变的
2.线程安全
String对象是不可变的,可以理解为常量,所以是线程安全的(如果对于这个一点有疑惑的,参考这篇文章)
StringBuffer对方法加了同步锁或者对被调用的方法加了同步锁,所以是线程安全的
StringBuilder没有对方法加同步锁,所以是非线程安全的
3.效率
String
拓展
常量池顾名思义就是常量,这是在编译期就确定好的,a+b == c 属于运行期的操作,只是a+b恰好生成了跟c内容一样的字符串
引用我看过一个大佬的话,常量池的意义就是为了节约内存,在编译期的时候对常量一样的引用统一,运行期的时候,如果生成一个新字符串对象时还要去比较是否与常量池的一样达到统一,这样内存确实节约了,但是运行效率就拉垮了
作为jvm的设计者,当然是重复就重复,不去判断是否一样
如果有写的不对的地方,欢迎指出。