JVM面试考点—— 值==问题(常量池)

简介: 基本类型的包装类和常量池java中基本类型的包装类的大部分都实现了常量池技术,即Byte,Short,Integer,Long,Character,Boolean。

基本类型的包装类和常量池

java中基本类型的包装类的大部分都实现了常量池技术,即Byte,Short,Integer,Long,Character,Boolean。

这5种包装类默认创建了数值[-128,127]的相应类型的缓存数据,但是超出此范围仍然会去创建新的对象。 两种浮点数类型的包装类Float,Double并没有实现常量池技术。

Integer与常量池

Integer i1 = 40;
Integer i2 = 40;
Integer i3 = 0;
Integer i4 = new Integer(40);
Integer i5 = new Integer(40);
Integer i6 = new Integer(0);
 
System.out.println("i1=i2   " + (i1 == i2));
System.out.println("i1=i2+i3   " + (i1 == i2 + i3));
System.out.println("i1=i4   " + (i1 == i4));
System.out.println("i4=i5   " + (i4 == i5));
System.out.println("i4=i5+i6   " + (i4 == i5 + i6));  
System.out.println("40=i5+i6   " + (40 == i5 + i6));
 
 
i1=i2   true
i1=i2+i3   true
i1=i4   false
i4=i5   false
i4=i5+i6   true
40=i5+i6   true

解释:

  • (1)Integer i1=40;Java在编译的时候会直接将代码封装成Integer i1=Integer.valueOf(40);,从而使用常量池中的对象。
  • (2)Integer i1 = new Integer(40);这种情况下会创建新的对象。
  • (3)语句i4 == i5 + i6,因为+这个操作符不适用于Integer对象,首先i5和i6进行自动拆箱操作,进行数值相加,即i4 == 40。然后Integer对象无法与数值进行直接比较,所以i4自动拆箱转为int值40,最终这条语句转为40 == 40进行数值比较。

String与常量池

String str1 = "abcd";
String str2 = new String("abcd");
System.out.println(str1==str2);//false
  
String str1 = "str";
String str2 = "ing";
String str3 = "str" + "ing";
String str4 = str1 + str2;
System.out.println(str3 == str4);//false
  
String str5 = "string";
System.out.println(str3 == str5);//true

解释:

  • (1)new String("abcd")是在常量池中拿对象,"abcd"是直接在堆内存空间创建一个新的对象。只要使用new方法,便需要创建新的对象。
  • (2)连接表达式 +
    只有使用引号包含文本的方式创建的String对象之间使用“+”连接产生的新对象才会被加入字符串池中。
    对于所有包含new方式新建对象(包括null)的“+”连接表达式,它所产生的新对象都不会被加入字符串池中。
public static final String A; // 常量A
public static final String B;    // 常量B
static {  
   A = "ab";  
   B = "cd";  
}  
public static void main(String[] args) {  
// 将两个常量用+连接对s进行初始化  
String s = A + B;  
String t = "abcd";  
if (s == t) {  
    System.out.println("s等于t,它们是同一个对象");  
  } else {  
    System.out.println("s不等于t,它们不是同一个对象");  
  }  
}

解释:

s不等于t,它们不是同一个对象。

A和B虽然被定义为常量,但是它们都没有马上被赋值。在运算出s的值之前,他们何时被赋值,以及被赋予什么样的值,都是个变数。因此A和B在被赋值之前,性质类似于一个变量。那么s就不能在编译期被确定,而只能在运行时被创建了。

String s1 = new String("xyz"); //创建了几个对象?

解释:

考虑类加载阶段和实际执行时。

  • (1)类加载对一个类只会进行一次。”xyz”在类加载时就已经创建并驻留了(如果该类被加载之前已经有”xyz”字符串被驻留过则不需要重复创建用于驻留的”xyz”实例)。驻留的字符串是放在全局共享的字符串常量池中的。
  • (2)在这段代码后续被运行的时候,”xyz”字面量对应的String实例已经固定了,不会再被重复创建。所以这段代码将常量池中的对象复制一份放到heap中,并且把heap中的这个对象的引用交给s1 持有。

这条语句创建了2个对象。

public static void main(String[] args) {
String s1 = new String("计算机");
String s2 = s1.intern();
String s3 = "计算机";
System.out.println("s1 == s2? " + (s1 == s2));
System.out.println("s3 == s2? " + (s3 == s2));
}
s1 == s2? false
s3 == s2? true

解释:

String的intern()方法会查找在常量池中是否存在一份equal相等的字符串,如果有则返回该字符串的引用,如果没有则添加自己的字符串进入常量池。

public class Test {public static void main(String[] args) {
 String hello = "Hello", lo = "lo";
 System.out.println((hello == "Hello") + " "); //true
 System.out.println((Other.hello == hello) + " "); //true
 System.out.println((other.Other.hello == hello) + " "); //true
 System.out.println((hello == ("Hel"+"lo")) + " "); //true
 System.out.println((hello == ("Hel"+lo)) + " "); //false
 System.out.println(hello == ("Hel"+lo).intern()); //true
 }
}
 
class Other {
 static String hello = "Hello";
}
 
 
package other;
 
public class Other {
 public static String hello = "Hello";
} 

解释:

在同包同类下,引用自同一String对象.

在同包不同类下,引用自同一String对象.

在不同包不同类下,依然引用自同一String对象.

在编译成.class时能够识别为同一字符串的,自动优化成常量,引用自同一String对象.

在运行时创建的字符串具有独立的内存地址,所以不引用自同一String对象.

JVM解读-方法区


个人介绍:

高广超 :多年一线互联网研发与架构设计经验,擅长设计与落地高可用、高性能互联网架构。

本文首发在 高广超的简书博客 转载请注明!

img_7015b3c64a6b1e4a95d4739adf2bbaa0.png
image.png
目录
相关文章
|
6月前
|
存储 Java
【面试题精讲】JVM-运行时数据区-StackOverFlowError
【面试题精讲】JVM-运行时数据区-StackOverFlowError
|
6天前
|
数据安全/隐私保护 Python
Python文件与目录操作:面试中的高频考点
【4月更文挑战第15天】本文介绍了Python文件和目录操作的面试重点,包括文件的读写、目录遍历及权限管理。强调了文件关闭、异常处理、特殊文件判断以及权限位和权限字符串的理解。提供了代码示例,如读写文件、遍历目录和更改文件权限,帮助读者在面试中表现出色。掌握这些技能将对编程求职之路大有裨益。
17 0
|
7天前
|
UED Python
掌握Python异常处理:面试中的关键考点
【4月更文挑战第14天】本文探讨了Python异常处理在面试中的重要性,涵盖核心概念、常见问题和易错点。异常处理涉及异常、捕获、异常链、自定义异常、finally子句和raise语句。面试中应注意避免过于宽泛的异常捕获、忽视异常链、在finally中误用return、自定义异常设计不实用以及异常处理与业务逻辑混杂等问题。通过理解并解决这些问题,可提升代码健壮性和面试表现。
21 0
|
1月前
|
存储 监控 算法
JVM 高级面试题及答案整理,最新面试题
JVM 高级面试题及答案整理,最新面试题
70 0
|
5月前
|
Arthas 监控 算法
JVM调优篇:探索Java性能优化的必备种子面试题
本文将带你深入了解JVM调优的重要性、常见问题以及一些实用的调优工具和方法,助你在面试的过程中轻松应对
131 0
JVM调优篇:探索Java性能优化的必备种子面试题
|
1月前
|
存储 算法 Java
JVM面试一文搞定!!!JVM详解!!!
JVM面试一文搞定!!!JVM详解!!!
|
2月前
|
存储 缓存 NoSQL
揭秘一线大厂Redis面试高频考点(3万字长文、吐血整理)
揭秘一线大厂Redis面试高频考点(3万字长文、吐血整理)
446 5
揭秘一线大厂Redis面试高频考点(3万字长文、吐血整理)
|
2月前
|
算法 编译器 C语言
C语言面试考点之二
C语言面试考点之二
14 0
|
2月前
|
存储 算法 编译器
面试 --- C考点
面试 --- C考点
36 0
|
3月前
|
设计模式 Java 关系型数据库
BAT等大厂年薪30W+面试清单:JVM\MySQL\设计模式\分布式\微服务
疫情影响下招聘名额缩减不少,但阿里、腾讯、抖音、快手等互联网公司却加快了人才招聘的节奏。这里根据自身的实际经历,整理了一份面试这些大厂的清单,希望能帮助到大家查漏补缺,攻克面试难关。