详解equals()和==以及int和Integer

详细探讨了equals和==在比较int和Integer以及对象之间相互比较的结果,及其原因

建议自己敲代码,复现每一种情况,加深了解,彻底搞懂其原理

Talk is cheap,Show you the code!

import java.util.ArrayList;

class Student{
    private int id;
    private String name;
    public Student(){};
    public Student(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

public class Main {
    public static void main(String[] args) {
        
        int i = 100;

        Integer a = 100;
        Integer b = 100;
        Integer a2 = 200;
        Integer b2 = 200;
        Integer c = new Integer(100);
        Integer d = new Integer(100);


        Student student1 = new Student(1,"zs");
        Student student2 = new Student(2,"ls");
        Student student3 = student1;

        System.out.println("**************************************int和Integer比较**********************************************\n");

        System.out.print("int i=100 和 Integer a=100 通过 == 比较: ");
        System.out.println(i == a);
        System.out.println("相等,因为包装类Integer 和 基本数据类型int 比较时,java会自动拆箱为int ,然后比较值是否相等,实际上就变为两个int变量值的比较\n");

        System.out.print("Integer a=100 和 Intager b=100 通过 == 比较:");
        System.out.println(a == b);
        System.out.println("因为Integer a = 100 系统将int类型的100自动装箱为Integer对象,然后比较内存地址");
        System.out.println("但是,当Int值在-128—127之间时,两个Integer变量引用的是IntegerCache中的同一个对象,所以比较内存地址相同\n");

        System.out.print("Integer a=100 和Integer a2=200 通过 == 比较:");
        System.out.println(a == a2);
        System.out.print("Integer a=100 和Integer a2=200 通过 equals() 比较:");
        System.out.println(a.equals(a2));
        System.out.println("因为Int值 a2=200 超过127,会通过new来创建一个新的对象,所以地址值和a不相同");
        System.out.println("Integer缓存了-128~127之间的数,这是在类加载期间就完成的。以后需要的时候直接指向它就可以了,省去了构造对象的开支,提高了效率\n");

        System.out.print("new Integer(100) 和 new Integer(100) 通过 == 比较:");
        System.out.println(c == d);
        System.out.print("new Integer(100) 和 new Integer(100) 通过 equals() 比较:");
        System.out.println(c.equals(d));
        System.out.println("因为Integer的equals() 方法会将Integer拆箱为int比较值是否相等,所以为true;而==直接比较地址值,所以为false\n");

        System.out.println("**************************************Object之间比较*************************************************");
        System.out.println("student1的内存地址值为:" + student1.hashCode());
        System.out.println("student2的内存地址值为:" + student2.hashCode());
        System.out.println("student3的内存地址值为:" + student3.hashCode());
        System.out.println("\n");

        System.out.print("student1 == student2:");
        System.out.println(student1 == student2);
        System.out.print("student1.equals(student2):");
        System.out.println(student1.equals(student2));
        System.out.println("对于引用类型,== 判断两个变量是否引用同一个对象,而 equals() 判断引用的对象是否等价\n");


        System.out.print("student1 == student3:");
        System.out.println(student1 == student3);
        System.out.print("student1.equals(student3):");
        System.out.println(student1.equals(student3));
        System.out.println("因为student3是指向student1的一个引用,内存地址相同,所以都为true\n");


    }
}

执行结果

**************************************int和Integer比较**********************************************

int i=100 和 Integer a=100 通过 == 比较: true
相等,因为包装类Integer 和 基本数据类型int 比较时,java会自动拆箱为int ,然后比较值是否相等,实际上就变为两个int变量值的比较

Integer a=100 和 Intager b=100 通过 == 比较:true
因为Integer a = 100 系统将int类型的100自动装箱为Integer对象,然后比较内存地址
但是,当Int值在-128—127之间时,两个Integer变量引用的是IntegerCache中的同一个对象,所以比较内存地址相同

Integer a=100 和Integer a2=200 通过 == 比较:false
Integer a=100 和Integer a2=200 通过 equals() 比较:false
因为Int值 a2=200 超过127,会通过new来创建一个新的对象,所以地址值和a不相同
Integer缓存了-128~127之间的数,这是在类加载期间就完成的。以后需要的时候直接指向它就可以了,省去了构造对象的开支,提高了效率

new Integer(100) 和 new Integer(100) 通过 == 比较:false
new Integer(100) 和 new Integer(100) 通过 equals() 比较:true
因为Integer的equals() 方法会将Integer拆箱为int比较值是否相等,所以为true;==直接比较地址值,所以为false

**************************************Object之间比较*************************************************
student1的内存地址值为:356573597
student2的内存地址值为:1735600054
student3的内存地址值为:356573597


student1 == student2:false
student1.equals(student2):false
对于引用类型,== 判断两个变量是否引用同一个对象,而 equals() 判断引用的对象是否等价

student1 == student3:true
student1.equals(student3):true
因为student3是指向student1的一个引用,内存地址相同,所以都为true

补充

Intager的equals()方法源码:

    public boolean equals(Object obj) {
        if (obj instanceof Integer) {
        	// 将Integer类型拆箱后,比较值是否相等
            return value == ((Integer)obj).intValue();
        }
        return false;
    }

Object的equals()方法源码:

  public boolean equals(Object obj) {
  		// 比较引用的是否相同
        return (this == obj);
    }

Intager的hashCode()方法源码:

   public int hashCode() {
   		// 返回int值
        return Integer.hashCode(value);
    }

Integer源码

 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() {}
    }

PS:时间仓促没写总结,建议自己代码实现,比背概念有用得多,有错误欢迎留言指正!


版权声明:本文为qq_43792852原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。