面试题答案
一键面试String的intern()方法对常量池优化的实现
- 常量池基础:在Java中,字符串常量池是一个存储字符串字面量的区域。当代码中出现字符串字面量时,如
String s = "hello";
,JVM首先会在常量池中查找是否已存在相同内容的字符串对象。如果存在,则直接返回常量池中该字符串对象的引用;如果不存在,则在常量池中创建一个新的字符串对象并返回其引用。 - intern()方法原理:
intern()
方法的作用是,如果常量池中已经包含一个等于此String
对象的字符串(用equals(Object)
方法确定),则返回常量池中该字符串的引用;否则,将此String
对象添加到常量池中,并返回此String
对象的引用。例如:
String s1 = new String("hello");
String s2 = s1.intern();
String s3 = "hello";
System.out.println(s2 == s3); // 输出true,因为s2和s3都指向常量池中的"hello"对象
这里new String("hello")
会在堆中创建一个新的String
对象,而intern()
方法会将该对象的内容添加到常量池中(如果常量池中不存在)并返回常量池中的引用。
适合使用intern()方法提升性能的场景
- 大量重复字符串场景:在处理大量重复的字符串时,使用
intern()
方法可以减少内存占用。例如,在处理日志文件分析,日志中可能会出现大量相同的字符串,如日志级别("INFO"、"ERROR"等)。
List<String> logLevels = new ArrayList<>();
for (int i = 0; i < 100000; i++) {
logLevels.add("INFO".intern());
}
如果不使用intern()
,这100000个"INFO"字符串会在堆中创建100000个不同的对象,占用大量内存。使用intern()
后,无论添加多少次"INFO",常量池中只会有一个"INFO"对象,大大减少了内存占用。
2. 字符串比较频繁场景:当需要频繁比较字符串时,使用intern()
方法可以提升比较性能。因为intern()
返回的是常量池中的引用,使用==
比较引用比使用equals
方法比较字符串内容效率更高。例如在一个权限验证系统中,角色名称(如"ADMIN"、"USER")会频繁用于权限判断和比较。
String role1 = "ADMIN".intern();
String role2 = "ADMIN".intern();
if (role1 == role2) {
// 角色判断逻辑
}
这里使用==
比较role1
和role2
,因为它们都是常量池中的引用,比较速度更快。如果不使用intern()
,则需要使用equals
方法比较字符串内容,性能相对较低。