黑马程序员技术交流社区

标题: 对象地址值相关问题 [打印本页]

作者: 李政    时间: 2012-9-13 15:18
标题: 对象地址值相关问题
本帖最后由 李政 于 2013-7-20 02:59 编辑

/*
如果定义一个Student类,并且重写hashCode方法和equals方法
创建两个hash值相同的对象,并且打印对象。



总结一        视频中讲打印对象的结果就是这个对象地址值,我觉得不一定
                因为对象的地址值是唯一的,
                如果是地址值的话,那这两个对象应该是一样,可事实肯定是不一样的对象。


总结二        equals方法返回true也不一定证明这两个对象相同,看到有同学说equals方法返回true
                那么两个对象一定相同,所有有了这么一个疑问。可能在不复写equals的情况下返回ture,
                那么这两个对象一定是同一个对象

问题        1 从网上看到,打印对象操作默认会调用对象的toString()方法,
                   一个类如果没有重写toString()方法的话,会从Object继承toString()方法,
                   而Object中的这个方法就是打印对象的哈希值hashCode()。
                   是这样吗? 我感觉是这样

                2 怎么查看对象的地址值?地址值是怎么通过哈希算法得出来的?

                3 总结的对不?

感受:自学不容易啊 容易走弯路,有时候想错了也没有人指正,造成一错再错,忘各位多多指教

*/

class Dizhi
{
        public static void main(String[] args)
        {        
               
                Student s1 = new Student(12,10);//参数不一样,两个对象是不相同的
                Student s2 = new Student(13,10);
               
               
                System.out.println(s1);//打印s1,为 Student@a
                System.out.println(s2);//打印s2,为 Student@a
               
                boolean b = s1.equals(s2);
                System.out.println(b);// 复写了equals方法,返回true

                System.out.println(s1.getAge());//结果是12,没有报错,
                                                                                //如果两个对象一样,会有两个age值,出现错误
                                                                                //再次说明两个对象一定是不一样的。
        }
}

class Student
{
private int age;
private int h;
Student(int age,int h)
{
        this.age = age;
        this.h = h;
}

public void setAge(int age)
        {
                this.age = age;
        }
public int getAge()
        {
                return age;
        }
public int hashCode()
        {
               
                return h;//返回hash值:h
        }
public boolean equals(Object obj)
        {
                return true;//返回true
        }
}

有了答案了:
问题中提到的equals方法和hashcode值,在不复写Object两个方法的前提下,equals就是比较对象是否相同,hashcode()也的确在打印的时候会被调用然后打印出地址值。
如果复写了equals,那仅仅是表面方法的调用,而并没有比较两个对象在内存中的本质。复写了hashcode方法后, 当对象被打印的时候,输出的只是一个表面的对象.toString方法,并不是正真的类名@地址值。也就是getClass().getName() + '@' + Integer.toHexString(hashCode() 。其中的hashcode方法只不过覆盖了原有的获取哈希值的方法而已,对象的地址值并没有因此而改变。地址值是唯一的。  我觉得真正的地址值是这样的,真正的地址值在对象创建的时候虚拟机已经自动生成了一个哈希值,并赋予了对象。与类中的hashcode方法毫无关系,它只是一个获取哈希值的方法。







作者: 李政    时间: 2012-9-13 15:20
请各位前辈先看代码再看问题和总结,忘多多指教
作者: 李政    时间: 2012-9-14 10:34
怎么没人呢
作者: 朱烈葵    时间: 2012-9-14 10:58
可以了,可以了,是这样的
作者: 夏天    时间: 2012-9-14 11:27
先留言再看问题。等我回复~~
作者: 程金    时间: 2012-9-14 11:41
java中不能得到对象的内存地址
hashcode算法有多种,一般来说是对对象地址或者,当前时间,字符串等等转换计算
java中,hashcode是本地方法实现,跟java程序没关系

在java中,在默认情况下,一个对象的toString()方法返回的字符串=="他的类的名字@hashcode()返回的hashcode的16进制编码"
hashcode()返回的是10进制编码
作者: 夏天    时间: 2012-9-14 12:17
首先说你的第一个总结。
System.out.println(s1);//打印s1,为 Student@a
System.out.println(s2);//打印s2,为 Student@a
你说你 new的s1,s2参数不一样,两个对象是不同的。所以你奇怪打印的地址值为什么相同
其实这里,不管你s1,s2的参数一样不一样。只要你new过一次,肯定就不是同一个对象了,new就是新创建,新开辟空间的意思。
可为什么输出的结果是相同的,都为Student@a 呢。
那是因为你重写了equals方法和hasCode方法,而你重写的方法,只返回一个相同的值,没有什么实质的比较,所以计算机会根据这两个判断对象是同一对象。

再说你的总结二。
“看到有同学说equals方法返回true,那么两个对象一定相同”那是因为,计算机判断两个对象是否相同,是如下判断的
首先,根据hasCode来判断,而hasCode方法,其实是根据某一算法来判断的,在非常巧合的情况下,有不同对象产生相同hasCode值
所以会通过重写equals方法来逐个比较对象的属性,就拿你这题来说equlas方法应该如下实现
public boolean equals(Object obj) {
  Student stu = (Student) obj;
  return this.h == stu.h && this.age == stu.age;
}

你的问题1是对的,如果没有重写toString方法,就会调用最父类的toString方法
问题2,3   就如下面所总结,不重写toString方法(也不能入你那样重写hascode和equals),直接打印对象,就是输出地址值。至于如何根据哈希算法得到地址,没有必要知道。

作者: 李政    时间: 2012-9-15 16:54
夏诗瑶 发表于 2012-9-14 12:17
首先说你的第一个总结。
System.out.println(s1);//打印s1,为 Student@a
System.out.println(s2);//打印s ...

讲的好,谢谢了:D:D:D:D:D:D:D:D
作者: 皮卫凯    时间: 2012-9-15 17:14
夏诗瑶 发表于 2012-9-14 12:17
首先说你的第一个总结。
System.out.println(s1);//打印s1,为 Student@a
System.out.println(s2);//打印s ...

                Student s1 = new Student(12,10);
                Student s2 = new Student(13,10);
               
               
                System.out.println(s1);//打印s1,为 Student@a
                System.out.println(s2);//打印s2,为 Student@a
               
                boolean b = s1.equals(s2);    //为什么你们都说这里覆写了equals(),
                System.out.println(b);           //这里为什么返回的是true。 s1跟s2  不是不同的对象么,  怎么会相同。

作者: 夏天    时间: 2012-9-15 19:45
皮卫凯 发表于 2012-9-15 17:14
Student s1 = new Student(12,10);
                Student s2 = new Student(13,10);
...

看楼主代码。。楼主自己复写的。。而且方法内就返回了一个true。




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2