hashCode和identityHashCode 的关系

Posted godtrue

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hashCode和identityHashCode 的关系相关的知识,希望对你有一定的参考价值。

1:首先看一下JDk API的观点

1-1:hashCode方法相关

1-2:identityHashCode()方法相关

2:此例的核心程序,对应的观点在注释中已经有所说明,请自己也动手实验一下看看!

import static java.lang.System.out;
/**
 * 一个对象的hashCode和identityHashCode 的关系:
 * 1:对象的hashCode,一般是通过将该对象的内部地址转换成一个整数来实现的
 * 2:当一个类没有重写Object类的hashCode()方法时,它的hashCode和identityHashCode是一致的
 * 3:当一个类重写了Object类的hashCode()方法时,它的hashCode则有重写的实现逻辑决定,此时的hashCode值一般就不再和对象本身的内部地址有相应的哈希关系了
 * 4:当null调用hashCode方法时,会抛出空指针异常,但是调用System.identityHashCode(null)方法时能正常的返回0这个值
 * 5:一个对象的identityHashCode能够始终和该对象的内部地址有一个相对应的关系,从这个角度来讲,它可以用于代表对象的引用地址,所以,在理解==这个操作运算符的时候是比较有用的
 *
 */

public class HashCodeTestMain
{
    /**
     * 输出对象重写的hashCode和唯一的hashCode
     * @param object
     */
    public static void printHashCodes(final Object object)
    {
        //输入对象的数据类型,以及调用toString()方法后返回的字符串形式,当对象为空时,此处输出null
        out.println("\\nThe object type is  : " + (object != null ? object.getClass().getName() : "null") + "\\nThe object value is : "+String.valueOf(object));
        //输出对象的hashCode值,当对象为空时,此处输出N/A
        out.println("Overridden hashCode : " + (object != null ? object.hashCode() : "N/A"));
        //输出对象的identityHashCode值,如果对应的类没有重写Object类的hashCode()方法,则和默认的hashCode值一致
        out.println("Identity   hashCode : " + System.identityHashCode(object));
    }

    /**
     * 主函数,程序执行的入口
     * @param arguments
     */
    public static void main(String[] arguments)
    {
        //基本数据类型的测试数据
        final byte _byte = 6;
        final char _char = \'s\';
        final short _short = 6;
        final int _int = 6;
        final long _long = 6L;
        final float _float = 6;
        final double _double= 6;
        final boolean _boolean = true;

        //包装类型的测试数据
        final Byte _Byte = 9;
        final Character _Character = \'S\';
        final Short _Short = 9;
        final Integer _Integer = 9;
        final Long _Long = 9L;
        final Float _Float = 9F;
        final Double _Double = 9D;
        final Boolean _Boolean = false;

        //字符串类型的测试数据
        final String someString = "someString";
        //null
        final String nullString = null;
        //自定义的测试对象
        final User user = new User(666,"godtrue");

        //基本数据类型的测试数据
        out.println("\\n测试基本数据类型的数据");
        printHashCodes(_byte);
        printHashCodes(_char);
        printHashCodes(_short);
        printHashCodes(_int);
        printHashCodes(_long);
        printHashCodes(_float);
        printHashCodes(_double);
        printHashCodes(_boolean);

        //包装类型的测试数据
        out.println("\\n测试包装数据类型的数据");
        printHashCodes(_Byte);
        printHashCodes(_Character);
        printHashCodes(_Short);
        printHashCodes(_Integer);
        printHashCodes(_Long);
        printHashCodes(_Float);
        printHashCodes(_Double);
        printHashCodes(_Boolean);

       //字符串类型的测试数据
        out.println("\\n测试字符串类型的数据");
        printHashCodes(someString);

        //null
        out.println("\\n测试null空对象");
        printHashCodes(nullString);

        //自定义的测试对象
        out.println("\\n测试自定义对象,构造此类的时候没有重写它的hashCode()方法");
        printHashCodes(user);
    }
}

3:User简单的自定义类,比较简单,没什么可讲的,关键是默认继承Object类,且没有重写hashCode()方法,不过重写了toString()方法

public class User {
    private Integer id;
    private String name;

    public User() {
    }

    public User(Integer id ,String name) {
        this.id = id;
        this.name = name;
    }

    @Override
    public String toString() {
        final StringBuffer sb = new StringBuffer("{\\"User\\":{");
        sb.append("\\"id\\":\\"").append(id).append("\\"").append(",");
        sb.append("\\"name\\":\\"").append(name).append("\\"");
        sb.append("}}");
        return sb.toString();
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

4:运行结果如下所示,不同的运行环境结果可能存在差异(win7+jdk7):

"C:\\Program Files\\Java\\jdk1.7.0_71\\bin\\java" -Didea.launcher.port=7532 "-Didea.launcher.bin.path=C:\\Program Files (x86)\\JetBrains\\IntelliJ IDEA 2016.1.3\\bin" -Dfile.encoding=UTF-8 -classpath "C:\\Program Files\\Java\\jdk1.7.0_71\\jre\\lib\\charsets.jar;C:\\Program Files\\Java\\jdk1.7.0_71\\jre\\lib\\deploy.jar;C:\\Program Files\\Java\\jdk1.7.0_71\\jre\\lib\\ext\\access-bridge-64.jar;C:\\Program Files\\Java\\jdk1.7.0_71\\jre\\lib\\ext\\dnsns.jar;C:\\Program Files\\Java\\jdk1.7.0_71\\jre\\lib\\ext\\jaccess.jar;C:\\Program Files\\Java\\jdk1.7.0_71\\jre\\lib\\ext\\localedata.jar;C:\\Program Files\\Java\\jdk1.7.0_71\\jre\\lib\\ext\\sunec.jar;C:\\Program Files\\Java\\jdk1.7.0_71\\jre\\lib\\ext\\sunjce_provider.jar;C:\\Program Files\\Java\\jdk1.7.0_71\\jre\\lib\\ext\\sunmscapi.jar;C:\\Program Files\\Java\\jdk1.7.0_71\\jre\\lib\\ext\\zipfs.jar;C:\\Program Files\\Java\\jdk1.7.0_71\\jre\\lib\\javaws.jar;C:\\Program Files\\Java\\jdk1.7.0_71\\jre\\lib\\jce.jar;C:\\Program Files\\Java\\jdk1.7.0_71\\jre\\lib\\jfr.jar;C:\\Program Files\\Java\\jdk1.7.0_71\\jre\\lib\\jfxrt.jar;C:\\Program Files\\Java\\jdk1.7.0_71\\jre\\lib\\jsse.jar;C:\\Program Files\\Java\\jdk1.7.0_71\\jre\\lib\\management-agent.jar;C:\\Program Files\\Java\\jdk1.7.0_71\\jre\\lib\\plugin.jar;C:\\Program Files\\Java\\jdk1.7.0_71\\jre\\lib\\resources.jar;C:\\Program Files\\Java\\jdk1.7.0_71\\jre\\lib\\rt.jar;D:\\workspace_test\\hello-world\\out\\production\\hello-world;C:\\Program Files (x86)\\JetBrains\\IntelliJ IDEA 2016.1.3\\lib\\idea_rt.jar" com.intellij.rt.execution.application.AppMain com.jd.test.equ.HashCodeTestMain

测试基本数据类型的数据

The object type is  : java.lang.Byte
The object value is : 6
Overridden hashCode : 6
Identity   hashCode : 692191789

The object type is  : java.lang.Character
The object value is : s
Overridden hashCode : 115
Identity   hashCode : 748481924

The object type is  : java.lang.Short
The object value is : 6
Overridden hashCode : 6
Identity   hashCode : 1923976189

The object type is  : java.lang.Integer
The object value is : 6
Overridden hashCode : 6
Identity   hashCode : 1606535644

The object type is  : java.lang.Long
The object value is : 6
Overridden hashCode : 6
Identity   hashCode : 732674977

The object type is  : java.lang.Float
The object value is : 6.0
Overridden hashCode : 1086324736
Identity   hashCode : 397106541

The object type is  : java.lang.Double
The object value is : 6.0
Overridden hashCode : 1075314688
Identity   hashCode : 1937943358

The object type is  : java.lang.Boolean
The object value is : true
Overridden hashCode : 1231
Identity   hashCode : 129543857

测试包装数据类型的数据

The object type is  : java.lang.Byte
The object value is : 9
Overridden hashCode : 9
Identity   hashCode : 1842670188

The object type is  : java.lang.Character
The object value is : S
Overridden hashCode : 83
Identity   hashCode : 896176329

The object type is  : java.lang.Short
The object value is : 9
Overridden hashCode : 9
Identity   hashCode : 1732745092

The object type is  : java.lang.Integer
The object value is : 9
Overridden hashCode : 9
Identity   hashCode : 221024277

The object type is  : java.lang.Long
The object value is : 9
Overridden hashCode : 9
Identity   hashCode : 1755797876

The object type is  : java.lang.Float
The object value is : 9.0
Overridden hashCode : 1091567616
Identity   hashCode : 1122108505

The object type is  : java.lang.Double
The object value is : 9.0
Overridden hashCode : 1075970048
Identity   hashCode : 76255581

The object type is  : java.lang.Boolean
The object value is : false
Overridden hashCode : 1237
Identity   hashCode : 1727296255

测试字符串类型的数据

The object type is  : java.lang.String
The object value is : someString
Overridden hashCode : -1264993755
Identity   hashCode : 984217639

测试null空对象

The object type is  : null
The object value is : null
Overridden hashCode : N/A
Identity   hashCode : 0

测试自定义对象,构造此类的时候没有重写它的hashCode()方法

The object type is  : com.jd.test.equ.User
The object value is : {"User":{"id":"666","name":"godtrue"}}
Overridden hashCode : 1826809479
Identity   hashCode : 1826809479

Process finished with exit code 0

5:上面的代码和注释已经抛出了我的观点,代码相对简单,可能还有一些繁琐,不过经过对比更能体现出自己观点的正确性,原本是想写一篇关于==操作符相关的博文的,后来发现要能清楚某些知识点,就需要先弄明白另外一些知识点,经过试验和查阅资料就有了此篇博文了,后续再补上相关联的知识点小结。

以上是关于hashCode和identityHashCode 的关系的主要内容,如果未能解决你的问题,请参考以下文章

Java学习:identityHashCode和hashCode方法

两段检验系统生成的identityHashCode是否重复的代码

使用 System.identityHashCode(obj) - 啥时候?为啥?

JVM 如何确保 System.identityHashCode() 永远不会改变?

Java-hashcode和equals方法

够强!一行代码就修复了我提的Dubbo的Bug。