Java中的128陷阱和new String(“xxx“)创建了几个对象问题

简介: Java中的128陷阱和new String(“xxx“)创建了几个对象问题

1、String str = new String("abc") 创建了几个字符串对象?

答案:1个或者2个


Ⅰ 如果字符串常量池中已经有"abc"存在,这种情况只需要新建 1 个对象,即 new 一个对象放在堆中。

Ⅱ 当字符串常量池中没有 "abc",此时会创建如下 2 个对象:

一个是字符串字变量 "abc" 所对应的、驻留(intern)在字符串常量池中的实例,字符串常量池只存放实例对象的引用。

另一个是通过 new String() 创建并初始化的,内容与"abc"相同的实例,在堆中。

总结: new String("xxx"); 如果字符串常量池intern中没有对应的xxx 那么就需要在字符串常量池新建,然后再在堆上new 一个对象。


2、String str1 = “abc” 和 String str2 = new String(“abc”)的区别?

两者看似都是创建了一个字符串对象,但在内存中却是不一样的:


String str1= “abc” 在编译期,JVM 会去字符串常量池来查找是否存在“abc”,如果不存在,就在字符串常量池中开辟一个空间来存储“abc”;如果存在,就不用新开辟空间。然后在栈内存中开辟一个名字为 str1 的空间,来存储 “abc” 在常量池中的地址值。

String str2 = new String("abc")在编译阶段 JVM 先去字符串常量池中查找是否存在 “abc”,如果过不存在,则在常量池中开辟一个空间存储 “abc”。在运行时期,通过 String 类的构造器在堆内存中 new 了一个空间,然后字符串常量池中的 “abc”复制一份存放到堆空间中,在栈中为 str2 开辟空间,存放堆中 new 出来的这个 String 对象的地址值。

也就是说,前者在初始化的时候可能创建了一个对象,也可能一个对象也没有创建;后者因为 new 关键字,至少在内存中创建了一个对象,也有可能是两个对象。

3、Java中的128陷阱?

先来看一个例子:

public static void main(String[] args) {
        Integer a=127,b=127;
        Integer c=128,d=128;
        System.out.println(a==b);// true
        System.out.println(c==d);// false
}

为什么出现这种情况呢?


我们都知道Integer 是 基本类型int 的包装类型。

在Java设计之初,设计者认为,开发者可能经常用到的数字范围都在100以内,而每次使用这些数字的包装类型都要开辟新空间的话,可能会占用大量的资源。

因此他们规定在-128~127之间的Integer类型的变量,直接指向常量池中的缓存地址,不再使用new去开辟出新的空间。

执行 Integer c = 128,相当于执行:Integer c = Integer.valueOf(128),基本类型自动转换为包装类的过程称为,自动装箱(autoboxing)。

这也是出现上述代码两次比较结果不同的原因!下面我们看下valueOf() 源码去体会下:

public static Integer valueOf(int i) {
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}

在Integer 中引入了IntegerCache 来缓存一定范围的值,默认情况下范围为:-128~127。

因此:上述代码中的 127 命中了 IntegerCache,所以 a 和 b 是相同对象,而 128 则没有命中,所以 c 和 d 是不同对象。


那么,如果想要正确比较的话c与d的话,就需要拆箱比较,即在变量后加intValue()方法:

public static void main(String[] args) {
        Integer a=127,b=127;
        Integer c=128,d=128;
        System.out.println(a==b);// true
        System.out.println(c.intValue()==d.intValue());// true
}

可以直接记住下面的表格,道理都是一样的:

image.png


相关文章
|
18小时前
|
SQL Java 数据库连接
15:MyBatis对象关系与映射结构-Java Spring
15:MyBatis对象关系与映射结构-Java Spring
12 4
|
2天前
|
Java
Java String类型转换成Date日期类型
Java String类型转换成Date日期类型
|
3天前
|
Java 索引
Java String应用与开发
Java String应用与开发
11 0
|
3天前
|
Java 编译器
【Java探索之旅】解密构造方法 对象初始化的关键一步
【Java探索之旅】解密构造方法 对象初始化的关键一步
8 1
|
3天前
|
Java
Java对象和类研究
Java对象和类研究
7 0
|
4天前
|
存储 安全 Java
聊聊Java中的常用类String
聊聊Java中的常用类String
9 0
|
4天前
|
机器学习/深度学习 人工智能 算法
java对象的比较
java对象的比较
15 0
java对象的比较
|
4天前
|
Java
Java学习——类与对象(二)
Java学习——类与对象(二)
|
4天前
|
存储 Java
Java对象是一种复杂的数据结构
【4月更文挑战第28天】Java对象是基于类的实例,包含属性和方法。类是对象的蓝图,实例化过程在堆内存中分配空间。对象属性存储各种数据,通过点号运算符访问,方法执行操作。Java提供内置对象如String、Integer,也可自定义对象以实现特定功能,如学生管理系统或电商网站。
7 1
|
4天前
|
Java C++
Java学习——类与对象(一)
Java学习——类与对象(一)