• java中equals,hashcode和==的区别


    ==

    java中的数据类型,可分为两类:

    1.基本数据类型,也称原始数据类型

    byte,short,char,int,long,float,double,boolean 他们之间的比较,应用双等号(==),比较的是他们的值。

    基本数据类型与其他内存==比较,其他类型都会拆箱转换成基本数据类型

    2.引用类型(类、接口、数组)

    当他们用(==)进行比较的时候,比较的是他们在内存中的存放地址,所以,除非是同一个new出来的对象,他们的比较后的结果为true,否则比较后结果为false。

    对象是放在堆中的,栈中存放的是对象的引用(地址)。由此可见'=='是对栈中的值进行比较的。如果要比较堆中对象的内容是否相同,那么就要重写equals方法了。

    	public static void main(String[] args) {
    		int int1 = 12;
    		int int2 = 12;
    		Integer Integer1 = new Integer(12);
    		Integer Integer2 = new Integer(12);
    		Integer Integer3 = new Integer(127);
    
    		Integer a1 = 127;
    		Integer b1 = 127;
    
    		Integer a = 128;
    		Integer b = 128;
    
    		String s1 = "str";
    		String s2 = "str";
    		String str1 = new String("str");
    		String str2 = new String("str");
    
    		System.out.println("int1==int2:" + (int1 == int2));
    		System.out.println("int1==Integer1:" + (int1 == Integer1));
    		System.out.println("Integer1==Integer2:" + (Integer1 == Integer2));
    		System.out.println("Integer3==b1:" + (Integer3 == b1));
    		System.out.println("a1==b1:" + (a1 == b1));
    		System.out.println("a==b:" + (a == b));
    
    		System.out.println("s1==s2:" + (s1 == s2));
    		System.out.println("s1==str1:" + (s1 == str1));
    		System.out.println("str1==str2:" + (str1 == str2));
    	}
    

    Output:

    int1==int2:true
    int1==Integer1:true  //Integer1会自动拆箱转换为int,Integer1==int1,也一样是true
    Integer1==Integer2:false //不同对象,内存存放地址不同
    Integer3==b1:false  //Integer3指向new的对象地址,b1指向缓存中127地址,地址不同,所以为false
    a1==b1:true
    a==b:false
    s1==s2:true
    s1==str1:false
    str1==str2:false
    

    Integer b1 = 127;java在编译的时候,被翻译成-> Integer b1 = Integer.valueOf(127);

    public static Integer valueOf(int i) {
            if (i >= IntegerCache.low && i <= IntegerCache.high)
                return IntegerCache.cache[i + (-IntegerCache.low)];
            return new Integer(i);
        }
    

    IntegerCache:

    private static class IntegerCache {
            static final int low = -128;
            static final int high;
            static final Integer cache[];
    
            static {
                // high value may be configured by property
                int h = 127;
                String integerCacheHighPropValue =
                    sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
                if (integerCacheHighPropValue != null) {
                    try {
                        int i = parseInt(integerCacheHighPropValue);
                        i = Math.max(i, 127);
                        // Maximum array size is Integer.MAX_VALUE
                        h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
                    } catch( NumberFormatException nfe) {
                        // If the property cannot be parsed into an int, ignore it.
                    }
                }
                high = h;
    
                cache = new Integer[(high - low) + 1];
                int j = low;
                for(int k = 0; k < cache.length; k++)
                    cache[k] = new Integer(j++);
    
                // range [-128, 127] must be interned (JLS7 5.1.7)
                assert IntegerCache.high >= 127;
            }
    
            private IntegerCache() {}
        }
    

    我们看到IntegerCache的low定义为-128,high默认定义为127.但是high是可以配置的,如果没有配置才是127.我们不去看配置的情况,因为java默认是没有配置的。看一下cache数组,长度为high-low+1,从-128开始到127,存在cache数组内。

    从上面的代码中可以看出,java在申请一个大于-128小于127的数时,其实是从cache中直接取出来用的,如果不在这个范围则是new了一个Integer对象。

    对于==,他比较的是地址。对于int来说比较的是值。

    对于equals,比较的是内容(要看equals的具体实现)。看一下Integer里面的实现:

      public boolean equals(Object obj) {
            if (obj instanceof Integer) {
                return value == ((Integer)obj).intValue();
            }
            return false;
        }
    

    只要都是Integer类型,equals比较的也是值

    Byte,Short,Long 的缓存池范围默认都是: -128 到 127。可以看出,Byte的所有值都在缓存区中,用它生成的相同值对象都是相等的。

    equals

    默认情况(没有覆盖equals方法)下equals方法都是调用Object类的equals方法,而Object的equals方法主要用于判断对象的内存地址引用是不是同一个地址(是不是同一个对象)。

    下面是Object类中equals方法:

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

    定义的equals与==是等效的

    要是类中覆盖了equals方法,那么就要根据具体的代码来确定equals方法的作用了,覆盖后一般都是通过对象的内容是否相等来判断对象是否相等。

    hasCode

    hashCode()方法返回的就是一个数值,从方法的名称上就可以看出,其目的是生成一个hash码。

    equals与hasCode关联

    • 如果两个对象equals,Java运行时环境会认为他们的hashcode一定相等。
    • 如果两个对象不equals,他们的hashcode有可能相等。
    • 如果两个对象hashcode相等,他们不一定equals。
    • 如果两个对象hashcode不相等,他们一定不equals。

    为什么覆盖equals时总要覆盖hashCode

    在每个覆盖了equals方法的类中,也必须覆盖hashCode方法。如果不这样做的话,就会违反Object.hashCode的通用约定,从而导致该类无法结合所有基于散列的集合一起正常运作,这样的集合包括HashMap、HashSet和Hashtable。

    因为如果不覆盖equals方法的话,相等的对象可能返回的不相同的hash code。

    比如上面这种情况就会出现在hashmap中,

    一个对象修改equals,判断里面的字段是否一致即相等,但是没有修改hasCode

    hashmap中的key根据hashCode分配到不同的元素,但是用equals尝试,key却是相等的,那就恶心了,会出现很多异常bug.

    参考:

    java中equals,hashcode和==的区别

    JAVA 拾遺--eqauls 和 hashCode 方法

    覆盖equals时总要覆盖hashCode

  • 相关阅读:
    linux安装nginx
    git配置多个SSH密钥
    webpack加载器安装node-sass失败的解决方法
    Vue-cli webpack打包之后index.html缺少引号的问题
    算法:一个数组中所有元素的最小公倍数
    JS 实现一个睡眠函数sleep
    剑指offer 牛客67道题集合
    剑指offer
    剑指offer
    剑指offer
  • 原文地址:https://www.cnblogs.com/hongdada/p/10272063.html
Copyright © 2020-2023  润新知