zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    Python学习札记(十五) 高级特性1 切片
    LeetCode Longest Substring Without Repeating Characters
    Python学习札记(十四) Function4 递归函数 & Hanoi Tower
    single number和变体
    tusen 刷题
    实验室网站
    leetcode 76. Minimum Window Substring
    leetcode 4. Median of Two Sorted Arrays
    leetcode 200. Number of Islands 、694 Number of Distinct Islands 、695. Max Area of Island 、130. Surrounded Regions 、434. Number of Islands II(lintcode) 并查集 、178. Graph Valid Tree(lintcode)
    刷题注意事项
  • 原文地址:https://www.cnblogs.com/hongdada/p/10272063.html
Copyright © 2011-2022 走看看