基于基本类型对“==”和“equals()”的探究
首先声明所有的探究都是基于jdk1.8.0_144版本上进行的。
开始之前我们先来看一段代码:
查看代码
int x = 0;
double y = 0.0;
System.out.println(x == y);//true
System.out.println(Integer.hashCode(x));//0
System.out.println(Double.hashCode(y));//0
System.out.println(Objects.equals(x, y));//false
这里我们声明了两个不同类型的变量,并且给他们赋了不同的值,可以用“==”进行判断是发现返回的值是true,这个返回结果并不是我们所期待的,调用equals()方法返回的结果才是我们想看到的。同时,我们也看到了两个变量他们的哈希码值是一样的,这又是为什么呢?
首先我们要知道java语言中是如何来给变量进行赋值的。
Double m = Double.valueOf(9.9);//包箱
double n = m.doubleValue();//拆箱
Integer x = Integer.valueOf(6);//包箱
int y = x.intValue();//拆箱
在Java中变量的赋值并不是我们所看到的那样单纯的将值赋给变量。每个基本数据类型Java中都会有一个对应的包装类,每个类中调用.valueOf()就是对值进行自动包箱,调用.基本类型名Value()自动拆箱。下面我们来看一个例子:
查看代码
System.out.println("==========Integer==========");
Integer a = new Integer(99);
Integer b= new Integer(99);
System.out.println(a == b);//false
System.out.println(b.equals(a));//true
Integer c = Integer.valueOf(99);
Integer d = Integer.valueOf(99);
System.out.println(c == d);//true
System.out.println(c.equals(d));//true
int e = c.intValue();
System.out.println(Integer.hashCode(e));//99
int f = d.intValue();
System.out.println(Integer.hashCode(f));//99
System.out.println(e == f);//true
System.out.println(Objects.equals(e,f));//true
这里我们先new了两个Integer类。此时堆中会有两个new的Integer类,用“==”进行判断返回值是false,由此我们可以看到“==”是比较两个对象的内存地址是否相同的。后面我们对数据进行Integer类型的包箱,此时用“==”进行判断返回值是true。好,我们来看一下valueOf()方法:
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
这时候我们发现valueOf()方法中有一个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() {}
}
/**
* Cache to support the object identity semantics of autoboxing for values between
* -128 and 127 (inclusive) as required by JLS.
*
* The cache is initialized on first usage. The size of the cache
* may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.
* During VM initialization, java.lang.Integer.IntegerCache.high property
* may be set and saved in the private system properties in the
* sun.misc.VM class.
*/
通过注解可以知道这个缓存池是存在一个范围的下限是-128,上限是127(包含127)。缓存在第一次使用是会被初始化,它的大小可能由AutoBoxCacheMax=<size>这个选项控制。此时,变量c,d都是存放缓存中99所在的内存地址,因此"=="判断返回的是true。
接下来我们来看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()比的是两个对象的值,所以即使不是同一个对象,他们的值是相同的那么返回的值也是true。
ok,我们Integer类讲完了那我们来看看Doule类看看会有什么不一样呢?我先看一段代码:
查看代码
System.out.println("==========Double==========");
Double j = new Double(123.0);
Double k = new Double(123.0);
System.out.println(j == k);//false
System.out.println(j.equals(k));//true
Double m = Double.valueOf(123);
Double n = Double.valueOf(123);
System.out.println(m == n);//false
System.out.println(m.equals(n));//true
System.out.println("------------------");
double x = m.doubleValue();
System.out.println(Double.hashCode(x));//1079951360
double y = n.doubleValue();
System.out.println(Double.hashCode(y));//1079951360
System.out.println("-------------------");
System.out.println(Objects.equals(x, y));//true
System.out.println(x == y);//true
如果按照前面Integer类的情况,我们调用完valueOf()方法后应该会初始化一个缓存区,我们会从缓存区中得到我们想到的数据,将数据在缓存区中的内存地址赋值给变量。可是实际上并不是这样的。
public static Double valueOf(double d) {
return new Double(d);
}
public Double(double value) {
this.value = value;
}
private final double value;
public double doubleValue() {
return value;
}
它会new一个新的Double类将数据进行包箱,所以“m==n”返回值是false,它没有我们上面所讲的缓存区这一个说法。上面我们讲了equals()是对于对象值的比较因此返回的是true;由于doubleValue()是直接返回Double类包箱的值,返回出x,y的hashCode()值发现他们的哈希码值是相同的即他们是同一个对象。所以“x==y”返回值也为true。
posted on 2022-03-23 18:00 vernier_caliper 阅读(33) 评论(0) 收藏 举报
浙公网安备 33010602011771号