一、为什么String使用final修饰?
从String的源码中可以看出String是被final修饰的不可继承类。
使用final修饰能够缓存结果,当你进行传参时不需要考虑谁会改变它的值;如果是可变类的话,则可能需要重新拷贝出来一个新的值进行传参,这样在性能上就会有一定的损失。
迫使String类设计成不可变的原因是安全,当你在调用其他方法时,比如调用一些系统级操作指令之前,可能会有一系列校验,如果是可变类的话,可能在你校验过后,它的内部的值又被改变了,这样有可能会引起严重的系统崩溃问题。另一个是高效,只有字符串是不可变时,我们才能实现字符串常量池,字符串常量池可以为我们缓存字符串,提高程序的运行效率。
二、==和equals的区别?
equals和==最大的区别就是一个是方法,一个是运算符。
== : 如果比较的对象是基本数据类型,则比较的数值是否相等;如果比较的是引用类型数据,则比较的是对象的地址值是否相等
equals:用来比较方法两个对象的内容是否相同
注意:equals方法不能用于基本数据类型的变量,如果没有对equals方法进行重写,则比较的是引用类型所指向的对象地址
三、String和StringBuffer、StringBuilder的区别?
它们都是可以用于存储和操作字符串,区别如下:
- String是只读字符串,意味着String引用的是字符串内容是不能更改的,例如:String str = “abc”; str = “def”;表面上是改变了,但是实际上是让str重新指向一个新的字符串对象,而原字符串对象没有改变,只是变成了一个不可及对象;
- StringBuffer / StringBuilder表示的字符串对象可以直接进行修改;
- StringBuilder是JDK5引入的,是线程不安全的,StringBuffer是JDK1时出现的,是线程安全的,因为它的方法被synchronized修饰,而StringBuilder的方法没有被synchronized修饰,但是正因为这样,StringBuilder的效率比StringBuffer更高。
四、String的itern()方法有什么含义?
如果不是用双引号声明的String对象,可以使用String提供的intern方法。intern 方法会从字符串常量池中查询当前字符串是否存在,若不存在就会将当前字符串放入常量池中。
五、以下语句创建了几个对象?
String str = new String("abc");
答:常量池中有"abc"字段是一个,常量池中没有"abc"字段则是两个(由于"abc"字段还没有,则创建的一个是new String创建的一个新的对象,一个是常量"abc"对象的内容创建出的新的String对象)
String str = "abc";
答:同上,如果常量池中有该字符串对象,则是1个,如果没有就是两个
new String("abc").intern(); //intern 方法会从字符串常量池中查询当前字符串是否存在,
//若不存在就会将当前字符串放入常量池中。
答:如果常量池中已经有该字符串的对象了就是1个,如果没有就是两个
六、String类型在JVM中是如何存储的?编译器对String做了哪些优化?
JDK1.8中JVM把String常量池移入堆中,针对String对象又做了特殊对待。
主要是把heap区域分成了两块,一块是字符串常量池,用于存储Java字符串常量对象,另一块用于存储普通对象及字符串对象。
例如:
String str1 = "abc"; //这个是存储在字符串常量池中的
String str2 = new String("xyz"); //这个是存储在堆当中的
总结:
1.双引号括起来的字符串,如"abc",是直接存储在字符串常量池中的
2.new关键字实例化的对象存在堆当中
由于String的不可变性,对其进行操作的效率会大大降低,但是对"+"操作符,编译器对其进行了优化
例如:
String temp = "ABC" + 200 + 'D';
等同于
String temp = new StringBuilder().append("ABC").append(200).append('D').toString();
这样就免于中间创建对象的浪费
当进行"+"操作符的几个对象都是字符串常量
String temp = "ABCD" + "E" + "fg";
编译器会自动优化为:
String temp = "ABCDEfg";
七、String常用方法?
- indexOf(): 查询字符串首次出现的下标位置
- lastIndexOf(): 查询字符串最后出现的下标位置
- contains(): 查询字符串是否包含另一个字符串
- toLowerCase():把字符串全部转成小写
- toUpperCase(): 把字符串全部转成大写
- length(): 查询字符串长度
- trim(): 去掉字符串的首尾空白
- replace(): 替换字符串中某些字符
- split(): 把字符串分割并返回
- join(): 把字符串数组转换成字符串
八、为什么针对安全保密高的信息,char[]比String好?
因为String是不可变的,就是说它一旦创建,就不能更改了,直到垃圾收集器将它收走。而字符数组中的元素是可以更改的。所以使用字符数组的话,安全保密性高的信息将不会存在于系统中被他人看到。