java中==和equals方法有什么区别详解

深入浅出简单详解

知兮丶青
阅读(665) 2017-12-09
java中==和equals方法有什么区别详解
java中==和equals方法有什么区别详解

java开放中,经常遇到判断。你在==和equals之间如何选择?


==和equals区别

6句话简单总结==和equals的区别:

== 是判断两个变量或实例是不是指向同一个内存空间

== 是指对内存地址进行比较

== 是引用是否相同

equals() 是判断两个变量或实例所指向的内存空间的值是不是相同

equals() 是对字符串的内容进行比较

equals() 指的是值是否相同


栈和堆

首先来简单了解下栈和堆

栈:存的是基本类型和对象的引用(引用、内容地址)

堆:存的是对象和数组(值、内容)


8种基本类型

java的8种基本数据类型

基本数据类型是存于栈中包括:byte,short,char,int,long,float,double,boolean

String数据类型是一种特殊数据类型,既可以用基本数据类型格式来创建,也可以用普通基本类型来创建。JVM会自动根据栈中数据的实际情况来决定是否有必要创建新对象。


实际运用

好了,简单了解了以上这些那些,可能你已经知道怎么用,在哪里用==和equals了。


例子1

首先来看一组常见的==使用。基本类型栈引用相同。

//基本数据类型用==比较
int a1 = 8;
int b1 = 8;
System.out.println("a1 == b1:" + (a1 == b1));
//a1 == b1:true


例子2

再来看一组特殊的比较字符串string。

1、与基本类型初始化语法一样的写法是存于常量词中,常量池中的对象可以共享。

//编译a1后再编译b2,常量池已有127,所以划分相同引用,内存地址是一样的
String a2 = "8";
String b2 = "8";
System.out.println("a2 == a2:" + (a2 == b2));
//a2 == a2:true

2、直接使用 new String()来创建。

//new直接开辟内存空间,a3和b3在栈中内存地址(引用)不一样
String a3 = new String("8");
String b3 = new String("8");
//引用比较
System.out.println("a3 == b3:" + (a3 == b3));
//a3 == b3:false
//值比较
System.out.println("a3 equals b3:" + (a3.equals(b3)));
//a3 equals b3:true


例子3

接下来再看下Integer比较那些事

//在值-128到127,==比较引用都是相同的。
Integer n1 = 127;
Integer m1 = 127;
System.out.println("n1 == m1:" + (n1 == m1));
//n1 == m1:true

接着看

Integer n2 = 128;
Integer m2 = 128;
System.out.println("n2 == m2:" + (n2 == m2));
//n2 == m2:false
System.out.println("n2 equals m2:" + (n2.equals(m2)));
//n2 equals m2:true

也许你有疑问:为何对象n1==m2是相等呢?而n2==m2又不相等呢?你在开发的那些年有没有写错呢?写错就大祸了,呵呵。

原来:

Integer把-128到127(可调)的整数都提前实例化了,存在Integer的缓存类IntegerCache中,用到在那范围的数值都是同一引用,不会再去实例化了。如果不是该范围直接new Integer()去创建新的实例。

来看看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) {
            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);
        }
        high = h;

        cache = new Integer[(high - low) + 1];
        int j = low;
        for(int k = 0; k < cache.length; k++)
            cache[k] = new Integer(j++);
    }

    private IntegerCache() {}
}

/**
 * Returns an {@code Integer} instance representing the specified
 * {@code int} value.  If a new {@code Integer} instance is not
 * required, this method should generally be used in preference to
 * the constructor {@link #Integer(int)}, as this method is likely
 * to yield significantly better space and time performance by
 * caching frequently requested values.
 *
 * This method will always cache values in the range -128 to 127,
 * inclusive, and may cache other values outside of this range.
 *
 * @param  i an {@code int} value.
 * @return an {@code Integer} instance representing {@code i}.
 * @since  1.5
 */
public static Integer valueOf(int i) {
    assert IntegerCache.high >= 127;
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}

...

由 valueOf(int i) 方法可见范围只有 -128 ~ 127 值。超出该范围则直接 return new Integer(i),所以对象的引用不再相同,因此不在那范围的值用==是不相等的。


至此完毕。



原创文章,转载请注明出处:https://www.weizhixi.com/article/26.html