当前位置: 代码迷 >> J2SE >> 比较对象大小== ,equals解决办法
  详细解决方案

比较对象大小== ,equals解决办法

热度:72   发布时间:2016-04-23 20:13:33.0
比较对象大小== ,equals
class Person{
 private String name;
 private int age;
 public Person(String name, int age){
  this.name =name;
  this.age=age;
 }
 public void setName(String name){
  this.name=name;
 }
 public String getName(){
  return this.name ;
 }
 public void setAge(int age){
  this.age =age;
 }
 public int getAge(){
  return this.age ;
 }
 public boolean compare(Person per){
  Person p1=this;
  Person p2=per;
  if(p1==p2){
  return true;
   
  }
  if((p1.name==p2.name)&&p1.age ==p2.age ){
      return true;
  }
  else{
   return false;
  }
 }
 
}
public class TestArrays{
 public static void main(String args[]){
  Person per1=new Person("aaa",12);
  Person per2=new Person("aaa",12);
  if(per1.compare(per2)){
   System.out.println("两个对象相等");
  }
  else{
   System.out.println("两个对象不相等");
  }
  
 }
}


为什么输出结果为: 两个对象相等
不是应该是: 两个对象不相等 么?
若将  if((p1.name==p2.name)&&p1.age ==p2.age ) 改成:
if(p1.name.equals(p2.name)&&p1.age ==p2.age ),输出结果应为:两个对象相等
------解决思路----------------------
 if((p1.name==p2.name)&&p1.age ==p2.age ){
       return true;
   }

这里返回 true 了

因为你在构建两个 Person 对象时,第一个参数 name 是一个字符串常量,java编译器会将这些对象放到一个叫常量池的地方,在同一个进程中,只要是引用到 xxx = "aaa" 的引用,会把它们全部指向同一个字符串,这是在编译时就确定的。因此 p1.name == p2.name 判断为真。

如果把构造器传入的两个 name 参数值改为由文件读取,或者使用
p1 = new Person(new String("aaa"), 12); 
p2 = new Person(new String("aaa"), 12);

将返回 false


------解决思路----------------------
同意二楼的说法,注意常量池
------解决思路----------------------
可以百度一下String类equals和hascode的关系,由于常量池的存在,这个类的比较很特别。有很多大牛的博客有专门的介绍。
------解决思路----------------------
首先,“==”运算符比较的是两个值;而eaquals方法则是根据定义者所定义的比较原则来比较调用对象和参数对象一种方式。
其次,值可以是基本数据类型的值,也可以是对象引用的值(但不是对象本身),也可以是常量池中的值。
第三,这两个语句
Person per1=new Person("aaa",12);
Person per2=new Person("aaa",12);
给构造函数传递的参数都是常量池中的字符串值,它们不仅值相同,而且是同一个对象。因此,无论是
p1.name.equals(p2.name)还是
p1.name==p2.name都得到true的结果。
第四,如果是如下两个语句
p1 = new Person(new String("aaa"), 12); 
p2 = new Person(new String("aaa"), 12);
则传递给的构造函数的参数是使用常量池中的"aaa"字符串的值分别构造的两个String类的实例对象的引用。当然这两个引用的值是不同的,因此,这两个对象在堆中是彼此独立的。因此,作为比较值的p1.name==p2.name的语句而言,产生的结果就是false,而p1.name.equals(p2.name)语句则返回true。这样就会导致两个Person对象实例的比较会出现不同的结果,即一个是不等,而另一个则是相等。
------解决思路----------------------
对,2楼正解,常量池。

再给你个例子
        

        String str1 = "aaa";
        String str2 = "aaa";
        String str3 = new String("aaa");
        if(str1 == str2 ){
            System.out.println("str1 = str2");
        }

        if(str1 == str3){
            System.out.println("str1 = str3");
        }else {
            System.out.println("str1 != str3");
        }


输出:
     str1 = str2
     str1 != str3

由于str1和str2直接用"aaa"这种常亮赋值方式,所以str1和str2都是常量池里的“aaa”这个常量的引用。
str3是新创见了一个String对象,所以不是常量池里"aaa"的引用。
------解决思路----------------------
这里的name的赋值使用的是, this.name = name;  而name是“aaa”, 两个对象的name都是常量池中的字符串"aaa",并未创建新的对象。都指向同一个aaa的引用。

建议去看下,String s = new String("xxxx").和String s = "xxx"区别。  这都是老掉牙的面试题,搞懂其中原理,以后都能一一理顺
  相关解决方案