Java数据类型
基础类型 | 字节 | 包装类型 |
---|---|---|
int | 4字节 | Integer |
byte | 1字节 | Byte |
short | 2字节 | Short |
long | 8字节 | Long |
float | 4字节 | Float |
double | 8字节 | Double |
char | 2字节 | Character |
boolean | 未定 | Boolean |
Java属于面向对象语言那么为什么会出现非对象类型数据(基础类型),因为基础数据类型是的虚拟机的运行速度更快而且占用内存更少。详情内容可以参见:Java为什么需要保留基本数据类型
在JavaSE5之前我们创建爱你Integer对象:
Integer i = new Integer(10);
从JavaSE5提供了自动装箱的特性时,我们可以更简单的创建基础类型的对象:
Integer a = 10;
int b = a;
从上面的代码我们可以简单的看出装箱、拆箱的操作:
Integer a = 10;
我们将10【装箱】生成Integer对象。int b = a;
我们将Integer【拆箱】转成int基础类型
我们这里先写一个简单的类,然后反编译看看它的字节码文件
public class Main {
public static void main(String[] args) {
Integer a = 10;
int b = a;
}
}
反编译出来的字节码文件:
Main字节码.jpg
Integer a = 10;
//实际执行的是Integer a = Integer.valueOf(10);
int b = a;
//实际执行的是int b = a.intValue();
我们先来看一道面试题:
public class Main {
public static void main(String[] args) {
Integer a = 10;
Integer b = 10;
Integer c = 128;
Integer d = 128;
System.out.println(a == b);
System.out.println(c == d);
}
}
内心怀揣自己的真是答案,我们看看下边的源代码: 先看看Integer装箱和拆箱的函数源码:
/**
* Returns the value of this {@code Integer} as an
* {@code int}.
*/
public int intValue() {
return value;
}
/**
* 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) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
/**
* 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.
*/
private static class IntegerCache {
/*********/
}
通过源码码我们可以发现,Integer在数据为[-128,127]之间时。使用了IntegerCache 返回缓存中对象的引用,否则new一个新的对象。
看到上面这个答案,有些同学就会想到:除过Integer之前还有其他的基础数据类型,那么其他的类型是否也是专业那个的呢?答案:是也不是。原理想想大家也都明白:
所以上面问题的正确答案分别是:true、false。
见识了"=="比较,现在看equals比较结果: 同样我们也先看一道题目:
public class Main {
public static void main(String[] args) {
Integer a = 1;
Integer b = 2;
Long c = 3L;
System.out.println(c == (a + b));
System.out.println(c.equals(a + b));
}
}
然后我们再看看源码:
/**
* 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;
}
在Java中我们知道操作"=="的两个数都是数据包装类型对象的引用的话,那么则是用来比较两个引用所指向的对象是不是同一个;而如果其中有一个操作数是表达式(即包含算术运算)则比较的是数值(即会触发自动拆箱的过程)。为什么呢,因为"=="两边引用数据类型必须一致,要不然无语错误。
所以我们得到上边题目的答案是:true、false。 因为第一次比较实际是先对数据进行拆箱然后比较,所以得到的结果是true;第二次比较实际是先拆箱(两个Integer对象拆箱)后装箱(将拆箱且计算后的数据再装箱),然后同Long对象比较,显然不是同一类型所以得到false。
以上问题及答案都是作者亲自敲出来的,想实际操作同学也可以反编译class文件看看【真相】’。