java equals == 的区别

主要区别

对于基本类型而言,== 比较的是二者值是否相等,对于应用类型而言,比较的是二者所引用的对象的地址是否相等,即比较二者是否指向同一个对象;
equals()是一个方法,只能比较引用数据类型(基本数据类型没有方法)。重写前比较的是地址值,重写后比一般是比较对象的属性。

Integer 的equals与==

Integer 重写了equals方法,实现源码如下

    /**
     * Compares this object to the specified object.  The result is
     * {@code true} if and only if the argument is not
     * {@code null} and is an {@code Integer} object that
     * contains the same {@code int} value as this object.
     *
     * @param   obj   the object to compare with.
     * @return  {@code true} if the objects are the same;
     *          {@code false} otherwise.
     */
    public boolean equals(Object obj) {
        if (obj instanceof Integer) {
            return value == ((Integer)obj).intValue();
        }
        return false;
    }

改方法先判断equals的入参obj的类型是否为Integer,如果不是则直接返回false,如果是,则判断值是否相等。
如果obj参入的是一个基本类型,编译器会给改参数自动装箱成对应的包装类型;
在equals方法里打上断点,可以发现,但执行

 a.equals(1L);

基本类型被装箱成Double类型

在这里插入图片描述
执行如下代码

public static void main(String[] args) {
        Integer a = 1;
        boolean result = a.equals(1L);
        System.out.println("reuslt " + result);

        result = a.equals(1);
        System.out.println("reuslt " + result);

    }

返回如下结果:
在这里插入图片描述

Integer与基本类型 == 的比较时,编译器会先将Integer拆箱成基本类型再比较,

    public static void main(String[] args) {
        Integer a = 1;
        boolean result = a == 1.0;
        System.out.println("reuslt " + result);
    }

Integer与Integer比较时,判断的是两个地址是否同一个地址;
注意:当某个Integer是通过Integer.valueOf()获得的,需要判断这个值得大小,当Integer超出某个范围内才会,new一个新的对象

Integer.valueOf()源码如下

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

IntegerCache 缓存
JAVA的Integer有IntegerCache会缓存-128~127之间的对象。
如:Integer x = 100,会调用Integer的valueOf()方法,这个方法就是返回一个Integer对象,但是在返回前,作了一个判断,判断要赋给对象的值是否在[-128,127]区间中,且IntegerCache(是Integer类的内部类,里面有一个Integer对象数组,用于存放已经存在的且范围在[-128,127]中的对象)中是否存在此对象,如果存在,则直接返回引用,否则,创建一个新对象返回。

public static void main(String[] args) {


        // Integer 与 基本类型equals比较时,基本类型会被编译成对应的装箱成对应的包装类型
        Integer a = 1;
        System.out.println(a.equals(1L));// 为false
        // Integer 与 基本类型== 比较时, 包装类型会被拆箱成对应的基本类型
        System.out.println(a == 1.0);// 为true

       //Integer 与 new出来的 Integer 比较时,无论如何都是false,因为始终不指向同一个对象

        System.out.println(a == new Integer(1));// 为false
        //Integer 与 Integer.valueOf 出来的 Integer 比较时
        System.out.println(a == Integer.valueOf(1));// 为true

        Integer b = 1200;
        System.out.println(b == Integer.valueOf(200));// 为false, 超出IntegerCache范围,

    }

String 的equals 与 ==

String equals方法源码

    /**
     * Compares this string to the specified object.  The result is {@code
     * true} if and only if the argument is not {@code null} and is a {@code
     * String} object that represents the same sequence of characters as this
     * object.
     *
     * @param  anObject
     *         The object to compare this {@code String} against
     *
     * @return  {@code true} if the given object represents a {@code String}
     *          equivalent to this string, {@code false} otherwise
     *
     * @see  #compareTo(String)
     * @see  #equalsIgnoreCase(String)
     */
    public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

先判断类型是否为String, 在判断两个String类型的char[]数组长度是否一致,最后遍历char数组中每一个元素是否相等;

与 Integer 类似,String 有两种创建方式,new和字面量”赋值。对于使用字面量赋值方式。JVM为了节省空间,会首先查找JVM中是否有对应的字符串常量。如果已经存在,则直接返回该常量或字符串实例对象的地址引用,而无需重新创建对象。对象new创建方式,JVM将添加字面量常量和创建字符串实例并返回实例引用。

        System.out.println("a" == "a");// 返回true
        System.out.println( "a" == String.valueOf("a"));// 为true
        System.out.println("a" == new String("a"));//为false

只有使用引号包含文本的方式创建的String对象之间使用“+”连接产生的新对象才会被加入字符串池中。对于所有包含new方式新建对象(包括null)的“+”连接表达式,它所产生的新对象都不会被加入字符串池中,


        String s1 = "a";
        String s2 = "b";
        String s3 = "a";
        String s4 = new String("b");
        String s5 = "ab";
        String s6 = "a" + "b";
        String s7 = "a" + s2;
        String s8 = s1 + "bc";
        String s9 = "abc";

        // 只有使用引号包含文本的方式创建的String对象之间使用“+”连接产生的新对象才会被加入字符串池中。对于所有包含new方式新建对象(包括null)的“+”连接表达式,它所产生的新对象都不会被加入字符串池中,

        System.out.println(s1 == s3);// true

        System.out.println(s2 == s4);// false

        System.out.println(s5 == s6);// true

        System.out.println(s5 == s7);// false

        System.out.println(s8 == s9);// false

对于 String.valueOf(), 该方法源码如下

    public static String valueOf(Object obj) {
        return (obj == null) ? "null" : obj.toString();
    }

String 类的toString方法

    public String toString() {
        return this;
    }

final修饰String

final修饰类的时候表示类不可被继承

final修饰方法的时候表示方法不能被重写

final修饰变量的时候,表示变量不可变

所以,final String c = “hello”;仅仅表示c不可变,不可再被重新赋值。(注意:这个String类是final的无关,那个是修饰String类的)

final修饰的String在相加的时候等同于字符串直接相加(注意这里相加的两个String 必须都被final修饰的):

final a = “a”,

final b = “b”;

a+b == “a”+“b” == “ab”

因为+号两边都是常量,其值在编译期就可以确定,由于编译器优化,在编译期就将+两边拼接合并了,直接合并成是一个常量"ab",这也解释了为什么 相加的两个String 必须都被final修饰的;

但是如果把final去掉,a+b == “a” + “b” 就是false了,因为不用final修饰,a和b都是对象,在编译期无法确定其值,所以要等到运行期再进行处理,处理方法:先new一个StringBuilder,然后append a和 b,最后相加的结果是一个堆中new出来的一个对象

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值