- Java有哪些基本类型
- 每种基本类型占用多少字节
- int类型的数据范围
- 什么是自动装箱拆箱
- short s1 = 1; s1 = s1 + 1;是否有编译问题? short s1 = 1; s1 +=1;是否有编译问题
- switch语句能否作用在byte上,能否作用在long上,能否作用在string上
- Integer f1 = 100, f2 = 100, f3 = 150, f4 = 150; f1 == f2? f3 == f4?
知识点详解:
Java基本类型及包装类
基本类型 | 包装类 | 字节长度 |
---|---|---|
byte | Byte | 1 |
boolean | Boolean | 1 |
short | Short | 2 |
char | Character | 2 |
int | Integer | 4 |
float | Float | 4 |
long | Long | 8 |
double | Double | 8 |
如果被问到数据范围,我们肯定不会记具体的数字,只需要知道类型占用的字节长度便可推算出来,但需要注意一点的是这个类型是否有符号位,比如int的数据范围,因为int是有正负号的,因此其范围为: -2^31 ~ 2^31-1
自动装箱拆箱
Java是面向对象的语言,但是为了编程方便,引入了8种基本类型,当这8种基本类型和对应的包装类混用的时候,就会涉及到转换,比如:
Integer i = 1;
int j = i;
第一行因为1是基本类型,但i是Integer类型,这时编译器就会自动将1包装为Integer对象,这种就叫装箱。同理第二行将Integer类型变量赋值给基本类型,编译器会自动将i转成基本类型,这种就是拆箱。关于自动装箱拆箱实现原理可以看下上面代码对应的字节码就一目了然了。
0 iconst_1
1 invokestatic #2 <java/lang/Integer.valueOf : (I)Ljava/lang/Integer;>
4 astore_1
5 aload_1
6 invokevirtual #3 <java/lang/Integer.intValue : ()I>
9 istore_2
10 return
自动装箱和拆箱分别调用了Integer.valueOf和Integer.intValue方法实现的。
对于最后一题:Integer f1 = 100, f2 = 100, f3 = 150, f4 = 150; f1 == f2? f3 == f4?
要想知道这题答案,需要看一下Integer.valueOf的源码。
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
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() {}
}
通过以上源码可以知道,Integer.valueOf方法内部使用了缓存,默认情况下整数范围在-128~127范围内的Integer会被缓存起来,因此这个范围内的Integer对象是共享的,这样做的原因和使用字符串常量池类似,为了减少内存消耗和减少临时对象创建提升性能。
由于f1和f2在这个范围内,所以f1和f2指向的是同一个引用,即f1==f2,f3和f4超出了这个范围,所以f3和f4指向的是不同的对象,即f3 != f4。
类型转换
基本类型之间可以互相转换,类型转换分为:
- 自动类型转换:编译器自动完成类型转换
- 强制类型转换:必须在程序中编写代码
自动类型转换规则:从存储范围小的类型到存储范围大的类型。
在Java中自动类型转换时对于整数默认类型是int,小数默认类型是double。因此对于如下代码:
short s1 = 1;
s1 = s1 + 1;
对于第二行s1 = s1+1,因为1是整数默认类型是int,而s1是short类型,因此首先需要将s1的值转成int类型,加上1后再将这个int类型值赋值给short类型的变量,由于Java中不允许将大的类型转成小类型,因此编译器会报错。除非使用强制类型转换: s1 = (short) (s1 + 1);
对于如下代码:
short s1 = 1;
s1 += 1;
这种编译器不会报错,具体原因看下字节码会很清楚,因为编译器自动使用了强制转换:s1 = (short) (s1 + 1);
知道了自动转换规则后,对于最后一题:switch语句能否作用在byte上,能否作用在long上,能否作用在string上?就清楚了。因为switch可以作用在int上,而byte可以自动转成int,所以switch可以作用在byte上,由于long不能自动转成int,因此switch不能作用在long上,对于能否作用在String上,在JDK1.7之前是不可以的,在1.7及之后的版本是可以的。顺便提一下switch也可以作用枚举上,其实现原理和作用在String上类似。
延伸一下switch作用在String和enum上的实现原理:
作用在String上,实际上编译器自动将switch和case里面的字符串替换成了该字符串的hashCode方法返回值了。作用在enum上,编译器将Enum替换成了枚举的ordinal方法返回值。本质上最终都被编译器转成int类型了。
看到这里相信你已经知道文章开头面试题的答案了吧。如何读者遇到其他和基本类型相关的面试题,欢迎留言补充!