• 中文
    • 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.5k
    • 请登录之后再进行评论

      登录

      赞助本站

      • 支付宝
      • 微信
      • QQ

      感谢一直支持本站的所有人!

      单栏布局 侧栏位置: