关于equals与"=="

==在java中是一个关系运算符,a == b 返回的运算结果是:如果两者的值相等返回true,否则返回false。

java中所有类有一个共同的父类Object,在java库中的Object类源码是这样写的:

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

而其所有子类均继承了这个方法。

java中指向对象的引用内部存储的值是这个对象在堆内存中的地址,所以说如果一个类没有重写(overwrite/override)从Object继承来的equals()方法的话,那么该类对象在调用equals方法进行比较时会通过比较两者的内存地址返回true or false。

 

给两个字面值相同的String类型字符串

  String s1 = "Hello";

  String s2 = "Hello";

  System.out.println(s1 == s2); //输出:true

  String s3 = new String("Hello");

  String s4 = new String("Hello");

  System.out.println(s3 == s4);//输出:false

以上代码说明如果采用"=="进行比较的话(Object类中的equals()方法原理),采用赋值声明的两个字面值相同的字符串比较返回值为true,采用new创建对象声明的两个字面值相同的字符串比较返回值为false,这显然是不符合人们认知习惯的。java库中的String类已经复写了equals方法,不管两个字符串是怎么声明而来,只要字面值相同,调用equals方法比较返回值都为true。

System.out.println(s1.equals(s2));//true

System.out.println(s3.equals(s4));//true

System.out.println(s1.equals(s4));//true

所以以后我们在比较两个字符串类型的数据时,要采用equals方法而不是"=="。

 

在现实中我们比较两个对象是否相等通常是想知道两者是否有相同的属性,比如一个Person类,有String name和int id属性,如果两个Person类引用的name和id属性均相同,那么我们认为这两个引用指向的是同一个人(相等);这时就需要复写从Object类继承来的equals方法。

 public boolean equals(Object obj){

  if(obj instanceof Person){

   Person p = (Person)obj;

   return (name.equals(p.name) && id == p.id);

  }

  return false;

 }

 ----------------------------------------------------------------------------------------------------

事实上,在java中带有双引号””的字符串会受到优待,放到方法区字符串常量池中。在创建字符串时会先去常量池找,找到就直接拿来用,找不到则创建一个存在里面。

String s1 = “abc”; 这段代码执行时会先去常量池找”abc”,没找到,创建”abc”;把池内”abc”的内存地址赋值给栈区的变量s1

String s2 = “abc”; 这段代码执行时会先去常量池找”abc”,找到;直接把池内”abc”的内存地址赋值给栈区的变量s2

String s3 = new String(“abc”);这段代码执行时会先去常量池找”abc”,找到(若没找到会先在常量池创建一个”abc”);执行new String()在堆内存创建字符串对象”abc”,将该对象地址赋值给栈区变量s3

posted @ 2015-10-30 23:25  GoQC  阅读(216)  评论(0)    收藏  举报