欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java中创建String、Integer、Charater直接赋值与new一个对象的区别

程序员文章站 2022-04-04 20:13:25
...

Java中创建String、Integer、Charater直接赋值与new一个对象的区别

    String、Integer、Long、short、charater等这几个对象都是有两种声明方式,比如String可以String str = "aaa"和String str = new String("aaa");两种方式却有本质上的不同,以至于在使用中一些判断方法会弄不清楚为什么这样,最基本的比如String的"=="和".equals()"的区别,相信对刚开始学习java的朋友会难以理解,这里发表一下我的拙见,希望能帮到大家。对于JVM的内存分配我了解的也是很表面浅显,大佬们也多多指正。

Java中创建String直接赋值和new String()的区别

public class TestString {
	public static void main(String[] args) {
		
		String str1 = new String("aaa");
		String str2 = new String("aaa");
		String str3 = str1;
		
		String str4 = "aaa";
		String str5 = "aaa";

		System.out.println(str1 == str2);
		System.out.println(str1 == str3);
		System.out.println(str4 == str5);
		System.out.println(str1 == str4);
	}
}

结果为:

false
true
true
false

    1、String str1 = new String("aaa"); 在栈中创建str1;在堆中new一个String对象,这里为了方便描述,记为A;"aaa"第一次出现,被丢进方法区的常量池中(是整个String对象放进常量池,而不是String的Value {'a','a','a'})。str1引用堆中的A,A用常量池中的"aaa"对象的值构造自己(可以看下图的String构造器)

    2、String str2 = new String("aaa"); 过程同1,把在堆中new的String对象记为B,str2是引用的B,所以str1==str2为false

    3、String str3 = str1; 在栈中创建str3,和str1都是引用堆中的A,所以str1==str3为true

    4、String str4 = "aaa"; 在栈中创建str4,str4引用方法区中的"aaa"对象,所以str1==str4为false

    5、String str5 = "aaa"; 在栈中创建str5,str5引用方法区中的"aaa"对象,所以str4==str5为true

详细请参考下图:

Java中创建String、Integer、Charater直接赋值与new一个对象的区别

延伸至Integer、Character对象

    对于Character:

Character c1 = 'a';
Character c2 = 'a';
Character c3 = new Character('a');
Character c4 = new Character('a');
		
System.out.println(c1 == c2);
System.out.println(c3 == c4);

结果为

    true

    false

分析的过程和String类似,这里就不再过多介绍

对于Integer、Long、Short:

public class TestNum{
	public static void main(String[] args) {
		Integer i1 = 127;
		Integer i2 = 127;
		Integer i3 = 128;
		Integer i4 = 128;
		
		Integer i5 = new Integer(127);
		Integer i6 = new Integer(127);
		Integer i7 = i5;
		
		System.out.println(i1 == i2);
		System.out.println(i3 == i4);
		System.out.println(i5 == i6);
		System.out.println(i1 == i6);
		System.out.println(i5 == i7);
	}
}

结果为:

    true
    false
    false
    false

    true

这里可能会产生疑问,尤其是第二个输入为false。

这里涉及到Ingeter的自动装箱和拆箱以及缓存问题。

执行Integer i1 = 127;时,显然左边为一个对象,右边为一个int基本数据类型,这样赋值是不对的。但却能编译通过,是因为编译过程中提供了自动装箱的功能,而对于-128到127之间的自动装箱,又涉及到了Integer缓存池的内容,为了提高效率,将这区间的整数放进了Integer缓存池,在使用时,i1、i2的比较其实是当做基本数据类型来进行的,因此相等。而Integer i3 = 128;不在缓存池范围内,装箱结果是和Integer i3 = new Integer(128);完全一样的。所有是两个对象的比较,因此不相等。