1 字符串
字符串在面试中也经常会被问到,String 是标准的不可变类,一旦创建了String对象,它的值就无法改变了。对它的任何改动,就是创建了一个新对象,再把引用指向该对象。
String对象赋值后会在常量池中缓存,如果下次创建会判定常量池中是否有缓存,如果有就直接返回给创建者。如果需要对字符串做很多修改,那么应该选择使用 StringBuffer & StringBuilder 类。
创建字符串的方式:直接定义、或者通过构造器创建字符串。
// 直接定义
String str = "stirng";
// 通过构造函数创建字符串
String str1 = new String("string");
问题1: String、StringBuffer、StringBuilder有什么区别?
String为字符串常量是不可变对象,StringBuffer与StringBuilder为字符串变量是可变对象,String每次修改相当于生成一个新对象,因此性能最低;StringBuffer使用synchronized来保证线程安全,性能优于String,但不如StringBuilder;StringBuilder为非线程安全类,StringBuffer为线程安全类。
问题2: 计算字符串长度
String str = “hello world”;
System.out.println(str.length());
问题3: 连接字符串
// +连接
String str = “hello” + “world”;
// +=
String str1 = “hello”;
str1 += “world”;
// 变量
String temp = “hello”;
String str2 = temp + “world”;
问题4: 比较字符串
// 比较字符串内容:
s1.equals(s2);
// 忽略字符串大小写:
s1.equalsIgnoreCase(s2);
问题5: 截取字符串
String string = "abcdef";
// 从下标为2的开始截取到最后,包含开始下标。结果:cdef
System.out.println(string.substring(2));
// 从下标为2的开始截取到下标为4的,包含开始下标但不包含结束下标。结果:cd
System.out.println(string.substring(2, 4));
问题6: JVM对字符串的优化
对于String的任何操作其实是创建了一个新对象,然后再把引用地址返回该对象,但JVM也会对String进行特殊处理,以此来提供程序的运行效率,比如以下代码:
String str = “ab”+”cd”+”ef”;
经过JVM优化后的代码是这样的:
String str = “abcdef”;
验证代码如下:
String str1 = “ab”+”cd”+”ef”;
String str2 = “abcdef”;
System.out.println(str1==str2);
执行的结果:true。
这就说明JVM在某些情况下会特殊处理String类型。
问题7: Sting、StringBuffer、StringBuilder的使用
字符串相关类型主要有这三种:String、StringBuffer、StringBuilder,其中StringBuffer、StringBuilder都是可以变的字符串类型,StringBuffer在字符串拼接时使用synchronized来保障线程安全,因此在多线程字符串拼接中推荐使用StringBuffer。
StringBuffer的使用:
StringBuffer sf = new StringBuffer(“lao”);
// 添加字符串到尾部
sf.append(“wang”);
// 执行结果:laowang
// 插入字符串到当前字符串下标的位置
sf.insert(0,”hi,”);
// 执行结果:hi,laowang
// 修改字符串中某个下标的值
sf.setCharAt(0,’H’);
// 执行结果:Hi,laowang
StringBuilder的使用方法和StringBuffer一样,它们都继承于AbstractStringBuilder。
问题8: “==”和equals的区别是什么?
“==”是运算符
- 如果比较的对象是基本数据类型,则比较的是其存储的值是否相等;
- 如果比较的是引用数据类型,则比较的是所指向的对象的地址值是否相等(是否是同一个对象)
equals()是Object的方法,用来比较两个对象的内容是否相等
- equals方法不能用于比较基本数据类型,如果没有对equals方法进行重写,则相当于==,比较的是引用类型的变量所指向的对象的地址值。
- 一般情况下,类会重写equals方法用来比较两个对象的内容是否相等。比如String类中的equals()是被重写了,比较的是对象的值。
问题9: String对象的intern()方法的作用?
intern()方法用来查找常量池中是否存在该字符值,如果常量池中不存在则先在常量池中创建,如果已经存在则直接返回。
String abc = "abc";
String cdf = abc.intern();
// 结果为true
System.out.println(abc == cdf);
问题10: String不可变性有哪些好处?
- 只有当字符串是不可变的,字符串常量池才能实现,字符串池的实现可以在运行时节约很多堆空间,因为不同的字符串变量都指向池中的同一字符串;
- 可以避免一些安全漏洞,比如在Socket编程中,主机名和端口都是以字符串的形式传入,因为字符串是不可变的,所以它的值是不可改变的,否则黑客们可以钻到空子,改变字符串指向的对象的值,造成安全漏洞;
- 多线程安全,因为字符串是不可变的,所以同一个字符串实例可以被多个线程共享,保证了多线程的安全性;
- 适合做缓存的key,因为字符串是不可变的,所以在它创建的时候哈希值就被缓存了,不需要重新计算,速度更快,所以字符串很适合做缓存的key。
问题11: String可以被继承吗?
不能被继承。因为String被声明为final(最终类),所以不能被继承。
public final clas String implements java.io.Serializable, Comparable<String>, CharSequence{//……}
问题12: String是基础类型吗?
String不是基础数据类型。基础数据类型有以下8种,分别是:boolean,byte,short,int,long,float、double、char。
下一篇:《面试宝典-Java I/O操作》