java基础之==与equals的区别

一.“==”的作用

在java中,“==”的作用:比较内存地址是否相同

  1. 对于引用数据类型:直接比较两个引用对象引用的堆内存地址是否相同;如:比较两个User对象,比较的是两个User对象在堆内存中执行的是否是同一个地址。
  2. 对于基本数据类型:比较基本数据类型的“值”是否相等;如:比较两个int类型的变量,比较的是两个变量的“值”是否相等。注意:对于基本数据类型(byte,short,char,int,float,double,long,boolean)来说,他们是作为常量在方法区中的常量池里面以HashSet策略存储起来的,对于"123" 这样的字符串也是相同的道理,在常量池中,一个常量只会对应一个地址,因此不管是再多的123或者"123" 这样的数据都只会存储一个地址,所以所有他们的引用都是指向的同一块地址,因此基本数据类型和String常量也是可以直接通过==来直接比较的。常常有人会说对于基本数据类型,"=="比较的是“值”相等,其实也是由于他们的内存地址相等。
  3. 对于基本数据类型的包装类型:(Byte, Short, Character,Integer,Float, Double,Long,  Boolean)除了Float和Double之外,其他的六种都是实现了常量池的,因此对于这些数据类型而言,一般我们也可以直接通过==来判断是否相等。
    int a = 128;
    int b = 128;
    System.out.println(a == b);
    //结果为:true
    
    Integer c = 1;
    Integer d = 1;
    System.out.println(c == d);
    //结果为:true
    
    Integer c11 = new Integer(127);
    Integer d11 = new Integer(127);
    System.out.println(c11 == d11);
    //结果为:false
    
    Integer c1 = 127;
    Integer d1 = 127;
    System.out.println(c1 == d1);
    //结果为:true
    
    Integer c2 = 128;
    Integer d2 = 128;
    System.out.println(c2 == d2);
    //结果为:false,为什么呢?
    
    因为 Integer 在常量池中的存储范围为[-128,127],127在这范围内,因此是直接存储于常量池的,而128不在这范围内,
    所以会在堆内存中创建一个新的对象来保存这个值,所以c2,d2分别指向了两个不同的堆内存地址,故而导致了不相等。
    

     

二.equals的作用

equals方法源于Object类,源码如下:

public boolean equals(Object obj) {
	return (this == obj);
}

 可以看到,在Object类中equals方法也是直接通过==来比较的,和==是没有任何区别的。

那么为什么又要说equlas和==的区别呢?是因为equals方法是可以由我们自己重写的,例如:java.lang.String 类,重写equals方法。

三.重写equals方法

在java.lang.String类中重写了equals方法,源码如下:

public boolean equals(Object anObject) {
	if (this == anObject) { //使用==,判断内存地址是否相等
		return true;
	}
	if (anObject instanceof String) {//判断是否为String类型
		String anotherString = (String)anObject;
		int n = value.length;
		if (n == anotherString.value.length) {//判断两个字符串长度是否相等
			char v1[] = value;
			char v2[] = anotherString.value;
			int i = 0;
			while (n-- != 0) {//单个字符循环判断是否相同
				if (v1[i] != v2[i])
					return false;
				i++;
			}
			return true;
		}
	}
	return false;
}

从源码可知:String中的equals方法比较的是字符串的内容是否一样。也就是说如果像String、Date这些重写equals的类,使用其equals方法的时候会和Object的不一样,比较的内容也不尽相同。 

//测试
String str1 = "123";
String str2 = new String("123");
String str3 = str2;

System.out.println(str1 == str2);//false
System.out.println(str1 == str3);//false
System.out.println(str2 == str3);//true
System.out.println(str1.equals(str2));//true
System.out.println(str1.equals(str3));//true
System.out.println(str2.equals(str3));//true

内存解释: 

new String("abc"),在对象创建字符串,内存地址不一样;

使用str1.intern()方法,编译器会将“abc”字符串添加到常量池中,并返回指向该常量的引用;如果此后再调用str2.intern(),因为常量池中已经存在了“abc”,因此直接返回常量池中“abc”的引用。

通过字面量赋值创建字符串(如:String str=”twm”)时,会先在常量池中查找是否存在相同的字符串,若存在,则将栈中的引用直接指向该字符串;若不存在,则在常量池中生成一个字符串,再将栈中的引用指向该字符串。

常量字符串的“+”操作,编译阶段直接会合成为一个字符串。如string str=”JA”+”VA”,在编译阶段会直接合并成语句String str=”JAVA”,于是会去常量池中查找是否存在”JAVA”,从而进行创建或引用。

对于final字段,编译期直接进行了常量替换(而对于非final字段则是在运行期进行赋值处理的)。
final String str1=”ja”;
final String str2=”va”;
String str3=str1+str2;
在编译时,直接替换成了String str3=”ja”+”va”.

常量字符串和变量拼接时(如:String str3=baseStr + “01”;)会调用stringBuilder.append()在堆上创建新的对象。 

String 的 intern() 方法返回一个字符串,内容与此字符串相同,但一定取自具有唯一字符串的池。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值