Java中equals()方法分析

Java中equals()方法分析

绝对是一道笔试题引发的‘血案’,前两天参见某公司的面试题,其中考到了关于Javaequals()方法的一道题。话不多说,先看一下这个题:

Integer i=100,j=100,s=128,k=128;
System.out.print(i==j);
System.out.print(i.equals(j));
System.out.print(s==k);
System.out.print(s.equals(k));

结果为:true true false true

原因:JVM使用缓存池来管理整型,并且范围在-128到127如果int直接超过这个返回,那么Integer会调用构造器创建一个新的Integer对象,例如题目中

s=128
k=128

其实质是相当于

Integer s=new Integer(128);

Integer K=new Integer(128);

上面题目代码可等价转换如下代码:

Integer i=new Integer(100);
Integer j=i;
Integer s=new Integer(128);
Integer K=new Integer(128);
System.out.print(i==j);
System.out.print(i.equals(j));
System.out.print(s==k);
System.out.print(s.equals(k));

在java中引用类型,比较方式有两种equals()==

equals()==比较变量类型区别:

使用==比较的变量有两种类型:

1、比较变量均为基本数值类型,则只要两个变量的值相等,就返回true;

2、比较变量为引用类型变量,只有它们指向同一个对象时,才返回true;

PS:==用于比较引用类型时必须一致或者为父子关系的对象。

使用equals()比较的变量为引用类型变量。


所有的类都继承与object类,我们先看以下objectequals()方法

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

可以了解到objectequals()方法是有==操作符来实现的。因此只要比较实例的类没有重写equals()方法,那么equals()方法与==比较的结果是一致的。都表示内存中存放地址的比较。

根据equals()方法是否被重写,将所有的引用类型分为:重写型(equals()方法被重写)、继承性

一、继承性(equals()方法没有被重写)

对于equals()方法没有被重写的引用类型,只要是被同一个new创建的实例,起比较的结果都为true,否则为false

此时== 与equals()等价

例如:

A a=new A();
A b=new A();
A c=a;
System.out.println(a.equals(b));
System.out.println(a==b);
System.out.println(a.equals(c));
System.out.println(a==c);

结果:false false true true

这表明new表示在JVM堆中创建一个新的空间来存放实例。所以ab变量指向不同的内存空间。ac指向同一空间。

一、重写型(equals()方法被重写)

这里介绍几个JDK中已经对equals()方法重写的类。

1、String

下来看一下String源码

public boolean equals(Object anObject) {  
	        if (this == anObject) {  
	            return true;  
	        }  
	        if (anObject instanceof 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;  
	    }  

源码分析:

if (this == anObject) :当两个String类型实例指向同一内存空间,答案是肯定的true

if  当两个实例并不指向同一内存空间时,分析源码可以知道,当这两个实例的字符串内容相同时,仍然返回true

总结:String equals()方法比较的实质是两个字符串内容是否相等,与内存地址无关

            String通过==比较的是内存地址(==比较内存地址是不会变的)

例如:

String a="one";
String b="one";
String c=new String("one");
System.out.print(a.equals(b));
System.out.print(a.equals(c));
System.out.println(a==b);
System.out.println(a==c);

于此类似的还有Integer、Date,它们都对equals()方法重写,比较的是指都是实例的内容而不是内存地址。

这里String的直接赋值也是JVM缓存池的作用在里面。因此a,b的内存地址一致。


回归到题目中,Integer的equals()也是比较的内容,因此只要内容值相等,equals()方法就返回true.
System.out.print(s.equals(k));
System.out.print(i.equals(j));
返回true;
按照道理将System.out.print(s==k);应该与System.out.print(i==j);一样都应该返回true.但是没有因为这里有点特殊,牵扯到了Java中常量池的内容。这里简要说一下,int常量池中初始化-128~127的范围,所以Integer i 当i的值在范围之内,取数值,而当i超出范围时,需new 一个新的实例,地址将发生变化。
因此System.out.print(s==k); 输出值为false

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值