这是我参与「第四届青训营 」笔记创作活动的的第11天。
昨天写一些java基础笔记的时候,碰到了一些很基础但是比较有趣的一些东西,java中‘==’ 的判断和String的一些特殊的东西,这里浅浅记录一下。
如果有兴趣,可以看看我之前的文章:红包算法之如何助你抢到大红包 | 青训营笔记 - 掘金 (juejin.cn),哈哈推广一波。
Java ‘==’ 如何判断
Integer 和 int 的 ==
首先我们看下如下代码:
Integer i1 = 127;
Integer i2 = 127;
Integer i3 = 128;
Integer i4 = 128;
int i5 = 128;
int i6 = 128;
System.out.println(i1 == i2); // true
System.out.println(i3 == i4); // false
System.out.println(i5 == i6); // true
结果正如注释那样:
true
false
true
这里其实更多的实验可以证明如下两条:
- int不管怎么比,只要值相同,那么 == 结果一定为true
- Integer在 -128~127 之间,值相同,那么 == 结果为true,超过这个区间,值相同与否,== 结果必为 false
那这是为什么呢?
封装类
- 封装类:也叫包装类。为了能将基本类型转化为对象进行处理,并能连接相关的方法。
- Java为每个基本数据类型都提供了包装类,这样便可以把这些基本类型转换为对象来进行处理了。
- 需要说明的是,Java是可以直接处理基本数据类型的,但在有些情况下需要将其作为对象来处理,这时就需要将其转换为包装类了。
- 八种包装类(对象不分大小):除了char对应Character,int对应Integer,其他的包装类都是把基本数据类型的首字母大写。
这也就是说,Integer a = 1 其实相当于 Integer a = new Integer(1)
Java中 == 和 Integer
- 如果是基本数据类型,则 == 比较的是值;如果是对象类型,则 == 比较的是对象的地址。
所以这就是为什么对于int,只要值相同,那么就是true
而对于类,比如说double 的包装类 Double
Double d1 = 1.0;
Double d2 = 1.0;
System.out.printl(d1 == d2); // false
但是那么为什么在-128 ~ 127 范围内,Integer又会‘判断值’呢
其实不是因为判断了值:
- 设计时为了减少Integer对象创建的开销,提升整体效率,预先创建好了共256个Integer对象供后续使用,如果传入value数值在**-128~127范围内,那么所有在这个范围内被创建的对象(句柄)实际都指向同一个地址**,即被预创建Integer对象所在的地址。
如果我们实在想判断值,那么我们可以用equals 的方法:
- 这里用 .equals 都是返回true的,equals的时候会先比较地址,然后再比较值
另外
对于
int a = 1;
Integer b = 1;
System.out.println(a == b); // true
这种情况是输出 true 的,因为Integer是int的封装类,int与Integer比较时,Integer会自动拆箱,也就是相当于两个 int 类型的值比较。
String 的 == 比较
对于以下代码:
String s1 = "abc";
String s2 = "abc";
String s3 = new String("abc");
System.out.println(s1 == s2); // ouput -> true
System.out.println(s1 == s3); // output->false
经过上面的学习,按理说也应该是对象的比较,那么两个应该都是false才对
那为什么s1跟s2比较为true呢,不妨看下面这些代码:
String g = "123";
String h = "123";
String i = new String("123");
System.out.println(Integer.toHexString(g.hashCode()));
System.out.println(Integer.toHexString(h.hashCode()));
System.out.println(Integer.toHexString(i.hashCode()));
System.out.println(Integer.toHexString(System.identityHashCode(g)));
System.out.println(Integer.toHexString(System.identityHashCode(h)));
System.out.println(Integer.toHexString(System.identityHashCode(i)));
想要理解输出的内容,我们要知道hashCode和identityHashCode
hashCode和identityHashCode
hashCode hashCode方法可以根据对象的内存地址算出来一个int数字,代表了该对象在内存中的存储位置。
有些类重写了hashcode,如String, 其源码如下:
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}
不难看出,如果字符串值相同的话,那么hashCode值一定相同
identityHashCode
而identityHashCode是由java.lang.System类提供了一个静态方法
public static native int identityHashCode(Object x);
identityHashCode根据对象的内存地址来计算hashcode,不管对象是不是重写了hashcode方法。
String
上面一个代码,三个字符串地址输出为:
be32
be32
be32
1b6d3586
1b6d3586
74a14482
可以看到,字符串均为“123”,故hashCode值相同,而g和h的identityHashCode值相同,i的identityHashCode不相同,这里就涉及到:
- 在Java中,String存在String pool,其中存放可以共享的字符串对象,在声明一个字符串对象时,会先去其中寻找是否存在相同的String内容,假设存在是不会创建新对象,故此时二者的内存地址相同。
- 但是new String会重新开辟地址,因此与之前String对象地址不同
其在内存中相当于:
到这里,就可以解释,为什么s1 == s2结果为true了。
最后
附测试源码:
import javax.sql.DataSource;
public class Mixed {
public static void main(String[] args) {
AboutVariable aboutVariable = new AboutVariable();
aboutVariable.stringTest();
}
}
class AboutVariable{
void test1() {
// Integer i1 = 127;
// Integer i2 = 127;
// Integer i3 = 128;
// Integer i4 = 128;
// int i5 = 128;
// int i6 = 128;
// System.out.println(i1 == i2); // true
// System.out.println(i3 == i4); // false
// System.out.println(i3 == i6); // true
Double d1 = 1.00;
Double d2 = 1.00;
System.out.println(d1 == d2);
}
void stringTest(){
String f = "123";
System.out.println(Integer.toHexString(f.hashCode()));
System.out.println(Integer.toHexString(System.identityHashCode(f)));
f = new String("122");
System.out.println(Integer.toHexString(f.hashCode()));
System.out.println(Integer.toHexString(System.identityHashCode(f)));
String g = "123";
String h = "123";
String i = new String("123");
System.out.println(Integer.toHexString(g.hashCode()));
System.out.println(Integer.toHexString(h.hashCode()));
System.out.println(Integer.toHexString(i.hashCode()));
System.out.println(Integer.toHexString(System.identityHashCode(g)));
System.out.println(Integer.toHexString(System.identityHashCode(h)));
System.out.println(Integer.toHexString(System.identityHashCode(i)));
System.out.println(g == h);
System.out.println(h == i);
}
}
如果这篇文章对你有帮助的话,请给我点一个赞吧,你的支持就是我创作的最大动力。
如有不对之处,欢迎指出~