java-数值,对象比较---"=="和"equals"以及自动装箱后的比较

1.==: ==比较的是的地址

如果进行比较的两个操作数都是数值类型,即使数据类型不一样,只要他们的值相同,都能返回true;如97=='a',或者t==5.0;

如果两个操作数是引用类型,那么只有两个引用变量的类型具有父子关系才可以比较,当指向同一个地址,即同一个对象的时候,才会返回true;

需要注意的地方1:

对于String类,当java程序直接使用如"hello"这种字符串直接量(编译时期就计算出来的字符串值)时,JVM会使用常量池来管理这些字符串;当使用new String("hello")的时候,JVM会先使用常量池管理"hello"直接量,再用String类的构造函数,new一个新的String对象;所以这里会产生两个对象,一个是编译时存放在常量池的"hello"字符串对象,一个是运行时new的String对象;

第一步,因为“hello”直接使用了双引号声明,故JVM会在运行时常量池中首先查找有没有该字符串,有则进入第二步;没有则直接在常量池中创建该字符串,然后进入第二步。第二步:在常量池中创建了一个String对象之后,由于使用了new,JVM会在Heap(堆)中创建一个内容相同的String对象,然后返回堆中String对象的引用。该行代码分别在常量池和堆中生成了两个内容相同的String对象。

需要注意的地方2:

public class Test1 {
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		String s1 = "sayhello";//这里在编译时期就在常量池产生了一个字符串常量;
		String s2 = "say";//这里在编译时期就在常量池产生了一个字符串常量;
		String s3 = "hello";//这里在编译时期就在常量池产生了一个字符串常量;
		String s4 = "say" + "hello";//编译期间优化成一个字符串,直接引用指向常量池里已经产生的"sayhello"
		String s5 = s2 + s3;//s2,s3都是变量,编译期不能确定s5是啥;用的是运行时产生在堆内存的s2,s3
		
		//注意的第一点已经说过了;这里因为常量池已经有了"sayhello",所以只产生了一个对象;
		String s6 = new String("sayhello");
		
		
		System.out.println(s1==s4);//true,s1和s4都指向常量池的"sayhello",所以是一个对象,一个地址
		System.out.println(s1==s5);//false,s1指向的是常量池里面的"sayhello",s5指向的是运行时堆内存中的"sayhello";
		System.out.println(s1==s6);//false,同上
	}

}

需要注意的地方3:

public class Test1 {
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		String s1 = "sayhello";//这里在编译时期就在常量池产生了一个字符串常量;
		final String s2 = "say";//这里在编译时期就在常量池产生了一个字符串常量;
		String s3 = "hello";//这里在编译时期就在常量池产生了一个字符串常量;
		
		String s4 = s2 + "hello";//因为s2加了final 实际也是常量,
		System.out.println(s1==s4);//在编译期能够确定;所以s4还是引用的常量池的字符串常量
	}

}



所以记住:当用双引号声明的String对象会在编译期间储存在常量池!

需要注意的地方4:

对于Integer:

public class Test2 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//首先要知道这里是自动装箱,在编译期间,这里被翻译成Integer a1 = Integer.valueOf(10);
		//然而在Integer类中,系统会把一个-128--127之间的整数自动装箱成Integer实例,存放在一个cache数组,
		//如果以后吧一个-128--127的整数自动装箱成一个Integer实例,会直接指向这个数组对于的元素;如果再这个
		//范围之外系统会重新创建一个Integer实例,所以a3和a4是两个不同的对象,而a1和a1都指向同一个数组元素;
		Integer a1 = 10;
		Integer a2 = 10;
		System.out.println(a1==a2);//true
		Integer a3 = 128;
		Integer a4 = 128;
		System.out.println(a3==a4);//false
	}

}

需要注意的地方5:

String str1 = new String("S") + new String("C");        
System.out.println(str1.intern() == str1);     
System.out.println(str1 == "SC"); 

true, false

String str2 = "SEUCalvin";//新加的一行代码,其余不变  
String str1 = new String("S")+ new String("C");      
System.out.println(str1.intern() == str1);   
System.out.println(str1 == "SC"); 

false,false;

str1.intern是去查找常量池是否含有SC字符串,如果有就返回常量池的引用,如果没有就返回堆上的引用;所以第一段的第一个是true,第二个SC是放在常量池的,所以str1是堆上的,所以返回false;

第二段的话因为常量池上已经有了,所以str1.intern返回常量池上的,和堆上的不一样;


2.equals:比较的是值,不过比较的规则是需要定义的;

首先,equals方法是object类的,object的equals规则是,只要两个比较的对象地址一样就算一样,和==的比较规则是一样的;

然而Integer,String等包装类是重写了equals方法的,他们的规则定义为只要两个对象的值一样,就算一样;

所以,如果是自己定义的类,就需要重写equals方法, 自己定义规则,否则就会继承Object的equals方法的规则;


例题:

Consider the following code:
Integer s=new Integer(9);
Integer t=new Integer(9);
Long u=new Long(9);
Which test would return true?


1.(s==u) ,因为, s 是 Integer 类型, u 是 Long 类型,两个不同类型的引用不能进行 == 比较。

2.(s==t) , s 是指向一个 9 的引用,而 t 也是一个指向 9 的引用,虽然都是指向 9 ,但却是指向不同的 9 ,即是两个不同的引用。因此 == 比较返回的是假。

3.(s.equals(t)) , Integer 的 equals 方法如下:

public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false ;
}
是 Integer 的实例且 value 值也相等的情况下返回真,其他返回假。
在这里, s 和 t 都是 Integer 类型且值都为 9 ,因此结果为真。

所以如果s.equals(u),类型不一样也会返回false;

4.(s.equals(9)) , 在进行 equals 比较之前,会对 9 调用 Integer.valueOf 方法,进行自动装箱 , 由于 IntegerCache 中已经存在 9 ,所以,直接返回其引用,引用相同, equals 就自然相同了。所以结果为真。

5.(s.equals( new Integer(9)) ,直接创建了一个新的 Integer 实例,但且值也为 9 ,所以,满足条件,返回真。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

obession

觉得有用可以打赏咖啡一杯~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值