java基本数据类型
java中一共有8种基本数据类型:byte,short,int,long,float,double,char,boolean
数据类型 | 字节 | 位数 | 取值范围 | 备注 |
---|---|---|---|---|
byte | 1byte | 8bit | -2^7 - 2^7-1 | 有符号 |
short | 2byte | 16bit | -2^15 - 2^15-1 | 有符号 |
int | 4byte | 32bit | -2^31 - 2^31-1 | 有符号 |
long | 8byte | 64bit | -2^63 - 2^63-1 | 有符号 |
float | 4byte | 32bit | 3.402823e+38 ~ 1.401298e-45 | |
double | 8byte | 64bit | 4.9000000e-324~ 1.797693e+308 | |
char | 2byte | 16bit | 0~2^16-1 | 无符号 |
boolean | 1byte | 8bit | true、false |
System.out.println("The value range of a byte type: " + Byte.MIN_VALUE + " ~ " + Byte.MAX_VALUE);
System.out.println("The value range of a short type: " + Short.MIN_VALUE + " ~ " + Short.MAX_VALUE);
System.out.println("The value range of a int type: " + Integer.MIN_VALUE + " ~ " + Integer.MAX_VALUE);
System.out.println("The value range of a long type: " + Long.MIN_VALUE + " ~ " + Long.MAX_VALUE);
System.out.println("The value range of a float type: " + Float.MIN_VALUE + " ~ " + Float.MAX_VALUE);
System.out.println("The value range of a double type: " + Double.MIN_VALUE + " ~ " + Double.MAX_VALUE);
System.out.println("The value range of a char type: " + Character.MIN_VALUE + " ~ " + Character.MAX_VALUE);
System.out.println("The value range of a boolean type: " + Boolean.TRUE + " ~ " + Boolean.FALSE);
}
/*
output:
The value range of a byte type: -128 ~ 127
The value range of a short type: -32768 ~ 32767
The value range of a int type: -2147483648 ~ 2147483647
The value range of a long type: -9223372036854775808 ~ 9223372036854775807
The value range of a float type: 1.4E-45 ~ 3.4028235E38
The value range of a double type: 4.9E-324 ~ 1.7976931348623157E308
The value range of a char type: ~
The value range of a boolean type: true ~ false
*/
基本数据类型之间的转换
1.自动类型转换
低类型可以自动转换为高类型。但是int -> float,long-> float, long->double
会造成精度丢失
public static void main(String[] args) {
byte b = 10;
// byte auto convert to short
short s = b;
// short auto convert to int
int i = s;
// int auto convert to long
long l = i;
char c = 'A';
// char auto convert to int
int ci = c;
// int auto convert to double
double cid = c;
System.out.println("cid = " + cid);
System.out.println("ci = " + ci);
// int auto convert to float,but precision loss
float f = ci;
System.out.println("f = " + f);
// float auto convert to double
double d = f;
System.out.println("d = " + d);
// long auto convert to float,but precision loss
System.out.println("l = " + l);
float lf = l;
System.out.println("lf = " + lf);
// long auto convert to double,but precision loss
System.out.println("l = " + l);
double ld = l;
System.out.println("ld = " + ld);
}
2.强制类型转换
高类型转低类型,需要强制转换。强制转换过程中可能发生数据溢出,必须警惕。
private static void testCasts(){
int fi = (int)3.0f;
System.out.println("fi = " + fi);
int di = (int)4.0d;
System.out.println("di = " + di);
int di2 = (int)5.5d;
System.out.println("di2 = " + di2);
byte b = (byte)134;
System.out.println("b = " + b);
short s = (short)32769;
System.out.println("s = " + s);
}
/*
output:
fi = 3
di = 4
di2 = 5
b = -122 //溢出
s = -32767
*/
3.运算导致的数据类型自动提升
口诀:
如果两个操作数其中有一个是double类型,另一个操作就会转换为double类型。
否则,如果其中一个操作数是float类型,另一个将会转换为float类型。
否则,如果其中一个操作数是long类型,另一个会转换为long类型。
否则,两个操作数都转换为int类型。
int i = 1 + 2;//两个int相加都为int类型
byte b1 = 1;
byte b2 = 2;
// byte bsum1 = b1 + b2; //编译不通过,会自动转换为int
int isum1 = b1 + b2;
short s2 = 2;
// byte bsum2 = b1 + s2; //编译不通过,会自动转换为int
int isum2 = b1 + s2;
// short s3 = s2 + 1; //编译不通过,会自动转换为int 经典面试题
s2 += 1; // 对它进行特殊处理—强制类型转化,s2 = (short)(s2 + 1)
//int di = 1 + 2.0; //编译不通过,会自动转换为double
//float di = 1 + 2.0; //编译不通过,会自动转换为double
double di = 1 + 2.0;
float fi = 1 + 2.0f;
java包装类型
基本数据类型 | 对应的包装类型 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
自动装箱与自动拆箱
自动装箱:
把基本类型转换为包装类类型
private static void testAutoBoxing(){ Integer i = 123; System.out.println(i);}
// javap 反编译可以看出
// java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
// java/io/PrintStream.println:(Ljava/lang/Object;)V
其原理是,编译时调用了Integer.valueOf()方法。
自动拆箱:
把包装类类型转换为基本类型
private static void testAutoUnBoxing(){
Integer i = new Integer(1);
int unBoxing = i;
System.out.println(unBoxing);
}
// javap 反编译
// java/lang/Integer."<init>":(I)V
// java/lang/Integer.intValue:()I
// java/io/PrintStream.println:(I)V
其原理是,编译时调用了Integer.intValue()方法。
自动装拆箱使用场景
-
集合类
List<Integer> list = new ArrayList<>(); for (int i = 0; i < 10; i++) { // list.add(Integer.valueOf(i)); list.add(i); }
-
包装类型和基本数据类型比较大小
// Integer i = Integer.valueOf(1); Integer i = 10; // i.intValue() < 11 System.out.println(i < 11);
-
包装类型的运算
// Integer i = Integer.valueOf(10); Integer i = 10; // Integer j = Integer.valueOf(10); Integer j = 20; // i.intValue() + j.intValue() System.out.println(i + j);
-
三目运算符
boolean flag = true; Integer i = 0; int j = 1; int k = flag ? i : j;
这其实是三目运算符的语法规范:当第二,第三位操作数分别为基本类型和对象时,其中的对象就会拆箱为基本类型进行操作。
阿里代码规约里新增:
-
函数参数与返回值
//自动拆箱 public int getNum1(Integer num) { return num; } //自动装箱 public Integer getNum2(int num) { return num; }
为什么需要包装类型
- 基本数据类型,只能进行赋值,运算,简单数据类型转换。包装类型提供了更加丰富的功能,例如Integer转16进制Integer.toHexString(),转二进制toBinaryString()等等。
- java里万物皆对象,集合里需要用到泛型,只能使用包装类型。
- 数据库里某个数值类型的字段是null,那么用int基本数据类型接收的时候,因为int的默认值是0,如果是null的话会报错,就会直接返回0。所以需要用Integer接收。
包装类型的缓存
Integer i = 10;
Integer j = 10;
System.out.println("i == j ? " + (i == j));
Integer m = 300;
Integer n = 300;
System.out.println("m == n ? " + (m == n));
// i == j ? true
// m == n ? false
Integer源码分析:
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() {}
}
其中的javadoc详细的说明了缓存支持-128到127之间的自动装箱过程。最大值127可以通过-XX:AutoBoxCacheMax=size
修改。 缓存通过一个for循环实现。从低到高并创建尽可能多的整数并存储在一个整数数组中。这个缓存会在Integer类第一次被使用的时候被初始化出来。以后,就可以使用缓存中包含的实例对象,而不是创建一个新的实例(在自动装箱的情况下)。
jdk1.6以后可以通过java.lang.Integer.IntegerCache.high
设置最大值。