• 中文
    • English
  • 注册
  • 查看作者
  • 关于Java中equals和==的详解

    一.  前言

    在初学Java的时候,整理过equals和==的详解的教程,但是一直没有时间发布在网站中,今天在学Algs4一书中,又再次遇到了这个问题,干脆将之前的教程整理发布出来

    二.  基本数据类型

    首先我们来看下两个基本数据类型的比较

    public class Equivalence {
    	  public static void main(String[] args) {
    	    int n1 = 47;
    	    int n2 = 47
    	    System.out.println(n1 == n2);
    	  }
    	}
    输出:
    true

    通过上面的程序我们可以看出,基本数据类型下,值相同,则==返回true ,若值不相同,则返回false

    三.  引用数据类型

    接下来,我们再看下两个对象的比较

    public class Equivalence {
    	  public static void main(String[] args) {
    	    Integer n1 = new Integer(47);
    	    Integer n2 = new Integer(47);
    	    System.out.println(n1 == n2);
        	System.out.println(n1.equals(n2));
        	n1 = n2;//n1的引用被n2的引用覆盖
    	    System.out.println(n1 == n2);
        	System.out.println(n1.equals(n2));
    
    	  }
    	}
    输出:
    false
    true
    true
    true

    n1和n2的值明明都是47,为什么基本数据类型下,n1 == n2 返回的的是true,而对象的比较,返回的却是false呢?

    其实是因为n1和n2这两个对象的值虽然相同,但是这两个对象的引用却是不同的,而== 和 != 比较的是对象的引用,所以第一个print输出的是false

    四. equals

    我们可以利用equals()方法的来比较两个对象的实际内容是否相同:所以第二个print输出的是true

    接下来,我们执行n1 =  n2; n1的引用被n2的引用覆盖,此时的n1和n2的引用还有值都是相同的

    所以第三个第四个输出的都是true

    当时整理到这里,以为自己已经理解了equals,其实不然,我们再来看一个例子

    class Value {
    	int i;
    }
    
    public class EqualsMethod {
    	public static void main(String[] args) {
    		String s1 = "a";
    		String s2 = "a";
    		
    		Value v1 = new Value();
    		Value v2 = new Value();
    		v1.i = v2.i = 100;
    		System.out.println(v1.equals(v2));
    		System.out.println(s1.equals(s2));
    		
    	}
    }
    
    输出:
    false
    true

    我们自己创建了Value类,然后创建两个Value类对象,并赋予相同的值,依旧采用equals方法,返回的却是false了,这是为什么呢?equals不是应该值相同,就返回true吗?这里为什么会是false呢?

    我们在eclipse里按住ctrl然后点击equals方法来(按照ctrl,然后把鼠标放在equals方法名上,会出现一个下划线,点进去即可)查看Object.class文件,发现equals方法实现如下:

    关于Java中equals和==的详解

    看到这里便明白了,这是因为equals的默认比较的是引用,所以我们需要重写equals方法,才可以达到预期的效果

    那么问题又来了,为什么s1和s2用equals返回的却是true呢?我们同样在eclipse里按住ctrl然后点击si和s2中的equals方法,查看String.class文件

    关于Java中equals和==的详解

    原来string默认重写了equals方法,重写后equals比较的是两个对象的值是否相同.

    那么v1和v2既不能用==来判断值是否相同,也不能用默认的equals方法来判断,我们该如何v1和v2比较值是否相等呢?其实很简单,我们模仿String中的重写equals的方法,对equals方法重写就可以了。代码如下:

    class Value {
    	int i;
    	
    	@Override
    	public boolean equals(Object obj) {
    		if (this == obj)
    			return true;
    		if (obj == null)
    			return false;
    		if (getClass() != obj.getClass())
    			return false;
    		Value other = (Value) obj;
    		if (i != other.i)
    			return false;
    		return true;
    	}
    	
    }
    
    public class EqualsMethod {
    	public static void main(String[] args) {
    		String s1 = "a";
    		String s2 = "a";
    		
    		Value v1 = new Value();
    		Value v2 = new Value();
    		v1.i = v2.i = 100;
    		System.out.println(v1.equals(v2));
    		System.out.println(s1.equals(s2));
    		
    	}
    }
    
    输出:
    true
    true

    现在,v1和v2中的equals方法在我们重写之后,比较的不再是v1和v2的引用,而是他们的值了,我们可以再次按住Ctrl 单击equals方法,发现不再跳转到Object,Class.而是跳转到我们刚才重写的equals方法中

    五.  其他知识点

    1.  基本数据类型

    • boolean——>1
    • byte——>1
    • char——>2
    • short——>2
    • int——>4
    • long——>8
    • Mfloat——>4
    • double——>8

    2.  引用数据类型

    • 类(class)
    • 接口(interface)
    • 字符串(String)
    • 数组([])
    • 空类型(null)

    3.  String 比较

    public class Test {
    	public static void main(String[] args) {
    		String s1 = "2";
    		String s2 = "2";
                    String s3 = new String("2");
                    String s4 = new String("2");
    		System.out.println(s1 == s2 );  //true
    		System.out.println(s1.equals(s2)); //true
                    System.out.println(s3 == s4);//false
    		System.out.println("s2 == s2" + s1 == s2);//false
    		System.out.println("s2 == s2 :" + (s1 == s2));// s2 == s2 :true
    	}
    }

    上面我们已经提到,==在java中是比较的是引用,即在内存中的地址,而String的equals()是比较字符串的内容,所以s1.equals(s2) 结果是true ,这个应该已经没有问题了,但是我们上面也提到了String是引用数据类型,那么 s1 == s2,比较的应该是引用,结果应该是false才对,可为什么结果是true呢?

    查阅资料,发现 :

    String s1 = “2”;

    java首先会在缓冲区查找是否有”String”这个常量对象,有就直接将其地址赋给s1,没有就创建一个”2″,然后将其赋给s1;然后

    String s2 = “2”;

    java同样会在缓冲区中查找”String”,这次能查找到了,因为s1创建了一个”String”,所以会将其地址赋给s2,如此,s1和s2便有了相同的地址,所以结果是true

    但是我们又发现,”s2 == s2″ + s1 == s2 的结果是false,这就奇怪了,s1 == s2 结果不是true吗?为什么这里又变成false了呢?其实这里涉及到运算符优先级的问题, + 优先级比 == 高,所以会先执行 “s2 == s2″ + s1 ,再将其结果 和s2 比较,结果当然是false了,所以需要修成”s2 == s2 :” + (s1 == s2) 这种写法才能得到我们期待的结果

    4.  数组比较

    public class Test {
    	public static void main(String[] args) {
    		String a[] = new String[2];
    		a[0] = "2";
    		a[1] = "2";
    		int b[] = new int[2];
    		b[0] = 2;
    		b[1] = 2;
    		System.out.println(a[0] == a[1]);//true
    		System.out.println(b[0] == b[1]);//true
    		System.out.println(args[0] == args[1] );
    		// args[0]和args[1]都是"2",但结果为false
    	}
    }

    六.  参考资料

    Thinking In Java

    Algorithms Fourth Edition

    barryhappy

  • 0
  • 0
  • 0
  • 4.6k
  • 请登录之后再进行评论

    登录
    单栏布局 侧栏位置: