Java基础1.1 — Java八大基本数据类型及其包装类
一、Java的八大基本数据类型
序号 | 数据类型 | 大小/位 | 封装类 | 默认值 | 可表示数据范围 |
---|---|---|---|---|---|
1 | byte | 8 | java.lang.Byte | 0 | -128~127 |
2 | short | 16 | java.lang.Short | 0 | -32768~32767 |
3 | int | 32 | java.lang.Integer | 0 | -2147483648 ~ 2147483647 |
4 | long | 64 | java.lang.Long | 0L | -9223372036854775808 ~ 9223372036854775807 |
5 | float | 32 | java.lang.Float | 0F | 1.4E-45~3.4028235E38 |
6 | double | 64 | java.lang.Double | 0D | 4.9E-324~1.7976931348623157E308 |
7 | char | 16 | java.lang.Character | 空 | 0~65535 |
8 | boolean | 8 | java.lang.Boolean | false | true或false |
无需记忆可表示范围,在JDK里面数据类型可承载的最大最小值已经在包装类里面用常量的形式表示出来了
如:Integer.MAX_VALUE
//byte
System.out.println("基本类型:byte二进制位数:"+Byte.SIZE);
System.out.println("包装类:java.lang.Byte");
System.out.println("最小值:Byte.MIN_VALUE="+Byte.MIN_VALUE);
System.out.println("最大值:Byte.MAX_VALUE="+Byte.MAX_VALUE);
System.out.println();
//short
System.out.println("基本类型:short二进制位数:"+Short.SIZE);
System.out.println("包装类:java.lang.Short");
System.out.println("最小值:Short.MIN_VALUE="+Short.MIN_VALUE);
System.out.println("最大值:Short.MAX_VALUE="+Short.MAX_VALUE);
System.out.println();
//int
System.out.println("基本类型:int二进制位数:"+Integer.SIZE);
System.out.println("包装类:java.lang.Integer");
System.out.println("最小值:Integer.MIN_VALUE="+Integer.MIN_VALUE);
System.out.println("最大值:Integer.MAX_VALUE="+Integer.MAX_VALUE);
System.out.println();
//long
System.out.println("基本类型:long二进制位数:"+Long.SIZE);
System.out.println("包装类:java.lang.Long");
System.out.println("最小值:Long.MIN_VALUE="+Long.MIN_VALUE);
System.out.println("最大值:Long.MAX_VALUE="+Long.MAX_VALUE);
System.out.println();
//float
System.out.println("基本类型:float二进制位数:"+Float.SIZE);
System.out.println("包装类:java.lang.Float");
System.out.println("最小值:Float.MIN_VALUE="+Float.MIN_VALUE);
System.out.println("最大值:Float.MAX_VALUE="+Float.MAX_VALUE);
System.out.println();
//double
System.out.println("基本类型:double二进制位数:"+Double.SIZE);
System.out.println("包装类:java.lang.Double");
System.out.println("最小值:Double.MIN_VALUE="+Double.MIN_VALUE);
System.out.println("最大值:Double.MAX_VALUE="+Double.MAX_VALUE);
System.out.println();
//char
System.out.println("基本类型:char二进制位数:"+Character.SIZE);
System.out.println("包装类:java.lang.Character");
//以数值形式而不是字符形式将Character.MIN_VALUE输出到控制台
System.out.println("最小值:Character.MIN_VALUE="+(int)Character.MIN_VALUE);
//以数值形式而不是字符形式将Character.MAX_VALUE输出到控制台
System.out.println("最大值:Character.MAX_VALUE="+(int)Character.MAX_VALUE);
}
1、进一步分类
- 整型:byte、short、int、long
- 浮点型:float、double
- 逻辑型:boolean
- 字符型:char
2、基本数据类型的转换
byte -> short -> int -> long -> float -> double
从左到右的数据类型转换都是隐式转换,无需强转。
从右到做的数据类型转换需要强转,并且会损失精度
二、包装类
java为每个基本数据类型都提供了包装类,包装类的默认值是null,并且内部提供了一些相关的操作方法。基本类型如int,直接在栈中分配空间,存储数值,而包装类是对象,需要在堆内存中分配空间,栈中存放着对应的堆空间地址
1、自动拆箱和自动装箱
在JDK1.5以后,提供了自动拆箱和自动装箱功能这样的"语法糖",如
//这是自动装箱
Integer i = 1;
//转换成了
Integer i = Integer.valueOf(1);
//所以,如果给i赋值null,再赋值给基本数据类型,就会导致NullPointerException
从字节码看出也是一样的
(通过idea搜索jclasslib bytecode viewer插件查看更方便,安装后在 View->Show Bytes Code With jclasslib)
0 iconst_1
1 invokestatic #2 <java/lang/Integer.valueOf>
4 astore_1
5 iconst_1
6 invokestatic #2 <java/lang/Integer.valueOf>
9 astore_2
10 return
同样地
//自动拆箱, 在表达式中只要有一个不是包装类型的都会自动拆箱
Integer i = 1;
int j = i;,
//后面一句转换成了
int j = i.intValue();
下面是字节码
0 iconst_1
1 invokestatic #2 <java/lang/Integer.valueOf>
4 astore_1
5 aload_1
6 invokevirtual #3 <java/lang/Integer.intValue>
9 istore_2
10 aload_1
11 invokevirtual #3 <java/lang/Integer.intValue>
14 istore_3
15 return
由此也可以看出,自动拆装箱属于编译特性
2、包装类的valueOf方法的缓存池
public static Byte valueOf(byte b) {
final int offset = 128;
return ByteCache.cache[(int)b + offset];
}
public static Short valueOf(short s) {
final int offset = 128;
int sAsInt = s;
if (sAsInt >= -128 && sAsInt <= 127) { // must cache
return ShortCache.cache[sAsInt + offset];
}
return new Short(s);
}
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
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 static Float valueOf(float f) {
return new Float(f);
}
public static Double valueOf(double d) {
return new Double(d);
}
public static Character valueOf(char c) {
if (c <= 127) { // must cache
return CharacterCache.cache[(int)c];
}
return new Character(c);
}
public static Boolean valueOf(boolean b) {
return (b ? TRUE : FALSE);
}
public static final Boolean TRUE = new Boolean(true);
public static final Boolean FALSE = new Boolean(false);
- Byte都是用缓存池里面的值
- Short、Integer、Long会缓存 -128~127
- Float和Double则直接返回,因为精度数不能每次都一样,所以缓存没有意义
- Character则是缓存 <=127
- Boolean,只有两个值,直接就用常量的形式表示出来了
三、一些需要注意的地方
- double和float,不能完全表示精度。如 : 3 x 0.1 = 0.3 ,这样会是false,所以在进行带精度计算时,需要用到BigDecimal
- char存储的是unicode编码字符,汉字也是unicode所以可以存储,但是一些生僻字不在unicode编码字符集中就不能显示
- switch中只能用byte、char、short、int,JDK1.7后可用String
- Java中的数值运算最低要求是int类型,如果参与运算的变量类型都没有超过int类型,则它们都会被自动升级为int类型再进行运算,所以它们运算后的结果类型也是int类型
- 两边都是包装类的equals比较值,== 比较引用,其中一边是表达式的,== 就是比较数值
四、一些题目
1.下面语句做了什么
Integer i = 1; //valueOf()自动装箱成Integer类型
i+=1;//先是将Integer类型的i自动拆箱成int,完成加法运算后再自动装箱成Integer
2.下面程序语句有什么问题
short s1 = 1;
s1 = s1 + 1; //编译不通过、需要强转
short s2 =1;
s2 += 1; //正常编译
Integer i = null;
int j = i; //NullPointException
3.下面程序的运行结果是什么
Integer i1 = 128;
Integer i2 = 128;
System.out.println(i1 == i2); //false 比较了对象
Integer i1 = 127;
Integer i2 = 127;
System.out.println(i1 == i2); //true 缓存了-128~127
Float f1 = 1f;
Float f2 = 1f;
System.out.println(f1 == f2) //false 始终new新对象