Java int and Integer
类型
区别 | int |
Integer |
注意 |
---|---|---|---|
Class | int |
java.lang.Integer |
int.class != Integer.class , 反射时需区分 |
内存位置 | 栈 | 堆 | Integer 跟其他普通对象一样存在堆里 |
初始值 | 0 | null | int 没法指定为 null |
int a = 123;
int b = 123;
Integer c = 123;
Integer d = 123;
Integer e = new Integer(123);
Integer f = new Integer(123);
Integer g = Integer.valueOf(123);
Integer h = Integer.valueOf(123);
用 System.identityHashCode
查看具体位置:
System.out.println(System.identityHashCode(a));//41903949
System.out.println(System.identityHashCode(b));//41903949
System.out.println(System.identityHashCode(c));//41903949
System.out.println(System.identityHashCode(d));//41903949
System.out.println(System.identityHashCode(e));//488970385
System.out.println(System.identityHashCode(f));//1209271652
System.out.println(System.identityHashCode(g));//41903949
System.out.println(System.identityHashCode(h));//41903949
- 123 是是一个 [-128, +127] 范围内的数, 后续会提到;
- 以上使用
equals
比较, 相互都相等; - 以上 Integer 对象之间使用
==
比较, 根据存储位置, 一致的才相等; - 以上 int 和 Integer 之间
==
比较, 受自动拆箱影响, 相等;
包装类对应表:
原始类型 | 包装类型 |
---|---|
boolean | Boolean |
byte | Byte |
char | Character |
float | Float |
double | Double |
int | Integer |
long | Long |
short | Short |
自动装箱 自动拆箱
先说 int 和 Integer 的装箱/拆箱:
//把 int 赋值给 Integer 即为自动装箱, 等效于 `Integer a = Integer.valueOf(123);`.
Integer a = 123;
//把 Integer 赋值给 int 即为自动拆箱, 等效于 `int b = a.intValue();`
int b = a;
要点:
- 对于 [-128, 127] 范围内的数,
Integer#valueOf
会使用缓存, 其他范围直接new Integer
(127 的上限可以配置). - int 赋值给 Object 会触发自动装箱;
- 遇到
==
+
*
等算数表达式的时候, 会触发自动拆箱, 都转为基本类型再比较. - 如果
==
比较两个对象, 则比较他们是否指向同一个对象; equals
左操作数只能是对象, 右操作数会先装箱再拆箱, 最终用==
比较基本数据类型;equals
比较 Integer 和 Long 直接返回 false;(++a).getClass()
=>class java.lang.Integer
具体实现
Integer
@HotSpotIntrinsicCandidate
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
Long
@HotSpotIntrinsicCandidate
public static Long valueOf(long l) {
final int offset = 128;
if (l >= -128 && l <= 127) { // will cache
return LongCache.cache[(int)l + offset];
}
return new Long(l);
}
public boolean equals(Object obj) {
if (obj instanceof Long) {
return value == ((Long)obj).longValue();
}
return false;
}
Double
@HotSpotIntrinsicCandidate
public static Double valueOf(double d) {
return new Double(d);
}
public boolean equals(Object obj) {
return (obj instanceof Double)
&& (doubleToLongBits(((Double)obj).value) ==
doubleToLongBits(value));
}
测验
int a = 123;
int aa = 123;
Integer b = 123;
Integer bb = 123;
Integer c = 1230;
Integer cc = 1230;
Long d = 1230L;
Long dd = 1230L;
Double e = 3.14D;
Double ee = 3.14D;
System.out.println(a == aa);//true
System.out.println(b == bb);//true
System.out.println(c == cc);//false
System.out.println(d == dd);//false
System.out.println(e == ee);//false
System.out.println(a == b);//true
System.out.println((b * 10) == c);//true
System.out.println((b * Integer.valueOf(10)) == c);//true
// System.out.println((c == d);//syntax error
System.out.println((c * 1) == d);//true
System.out.println(c.equals(cc));//true
System.out.println(c.equals(1230));//true
System.out.println(c.equals(1230L));//false
System.out.println(c.equals(d));//false
System.out.println(d.equals(1230));//false
System.out.println(d.equals(1230L));//true
System.out.println(e.equals(ee));//true
System.out.println(e.equals(3.14D));//true
设计模式
对于 Integer 类来说, 他使用了 享元模式, 其中 内部的 value
是他的 元
.
享元模式跟单例结构上看起来有点类似, 区别是享元返回的对象不一定都指向同一个. 就如上面例子所示, 超出 [-128, +127] 范围的数会得到不同的两个对象.