基本类型 | 大小 | 最小值 | 最大值 | 字段默认值 | 包装器类型 |
---|---|---|---|---|---|
boolean | — | — | — | false | Boolean |
char | 16 bits | ‘\u0000’(即为0) | ‘\uffff’ | ‘\u0000’ | Character |
byte | 8 bits | -128 | +127 | (byte)0 | Byte |
short | 16 bits | -2 | +2-1 | (short)0 | Short |
int | 32 bits | -2 | +2-1 | 0 | Integer |
long | 64 bits | -2 | +2-1 | 0L | Long |
float | 32 bits | -3.4E38(-3.4×10) | 3.4E38(3.4×10) | 0.0f | Float |
double | 64 bits | -1.7E308(-1.7×10) | 1.7E308(1.7×10) | 0.0d | Double |
void | — | — | — | — | Void |
基本类型
布尔型
boolean
boolean类型只有两个值true和false,默认为false。boolean与是否为0没有任何关系,但是可以根据想要的逻辑进行转换。
字符型
char
Java使用Unicode字符集表示字符,Unicode是完全国际化的字符集,可以表示全部人类语言中的字符。Unicode需要16位宽,所以Java中的char类型也使用16 bit表示。 赋值可能是这样的:
char ch1 = 88;
char ch2 = 'A';
char ch3 = '汉';
ASCII字符集占用了Unicode的前127个值。之所以把char归入整型,是因为Java为char提供算术运算支持,例如可以ch2++;之后ch2就变成Y。当char进行加减乘除运算的时候,也被转换成int类型,必须显式转化回来。
整型
byte
byte 由1个字节8位表示,是最小的整数类型。主要用于节省内存空间关键。
当操作来自网络、文件或者其他 IO 的数据流时,byte类型特别有用。
// byte常见问题
public void test(byte b);
test(0); // 编译器报错,类型不兼容
对byte类型进行数学运算时,会自动提升为int类型,如果表达式中有double或者float等类型,也是自动提升。
byte s1 = 100;
byte s2 = 'a';
// 下列代码是错误的:
byte sum = s1 + s2;//should cast by (byte)
short
short可能是最不常用的类型了。可以通过整型字面值或者字符字面值赋值,前提是不超出范围(16 bit)。
short类型参与运算的时候,一样被提升为int或者更高的类型。(顺序为 byte short int long float double).
//由于 1 是 int 类型,因此 s1+1 运算结果也是 int型,需要强制转换类型才能赋值给 short 型。
short s1 = 1; s1 = s1 + 1 ;// 编译错误
//s1+= 1;相当于 s1 = (short(s1 + 1);其中有隐含的强制类型转换。
short s1 = 1; s1 += 1;//编译正常
int
有符号的二进制补码表示的整数。常用语控制循环,注意byte 和 short在运算中会被提升为int类型或更高。
Java 8以后,可以使用int类型表示无符号32位整数[ 0, 2^31 - 1]。
long
当需要计算非常大的数时,如果int不足以容纳大小,可以使用long类型。如果long也不够,可以使用BigInteger类。
浮点类型
float
对应单精度浮点数,遵循IEEE 754规范。
运行速度相比double更快,占内存更小,但是当数值非常大或者非常小的时候会变得不精确。
// 精度要求不高的时候可以使用float类型,声明赋值示例:
float f1 =10;
f1 = 10L;
f1 = 10.0f; //f1 = 10.0;默认为double
可以将byte、short、int、long、char赋给float类型,Java自动完成转换。
double
将浮点字面值赋给某个变量时,如果不显示在字面值后面加f或者F,则默认为double类型。
java.lang.Math中的函数都采用double类型。
如果double和float都无法达到想要的精度,可以使用BigDecimal类。
字面值(Literal)
在 Java 源代码中,字面值用于表示固定的值(fixed value),直接展示在代码里,而不需要计算。数值型的字面值是最常见的,字符串字面值可以算是一种,当然也可以把特殊的 null 当做字面值。字面值大体上可以分为整型字面值、浮点字面值、字符和字符串字面值、特殊字面值。
整型字面值
整型字面值可以用十进制、16、8、2进制来表示。
2、8、16进制的表示分别在最前面加上0B(0b)、0、0X(0x)即可,当然基数不能超出进制的范围
一般情况下,字面值创建的是int类型
int字面值可以赋值给byte short char long int,只要字面值在目标范围以内,Java会自动完成转换
创建一个int类型无法表示的long类型,则需要在字面值最后面加上L或者l。通常建议使用容易区分的L
整型字面值包括int字面值和long字面值。
- 十进制(Decimal):其位数由数字0〜9组成;这是您每天使用的数字系统
- 十六进制(Hexadecimal):其位数由数字0到9和字母A至F的组成
- 二进制(Binary):其位数由数字0和1的(可以在 Java SE 7 和更高版本创建二进制字面值)
使用的语法:
// The number 26, in decimal
int decVal = 26;
// The number 26, in hexadecimal
int hexVal = 0x1a;
// The number 26, in binary
int binVal = 0b11010;
浮点字面值
浮点字面值简单的理解可以理解为小数。分为float字面值和double字面值
float字面值:在小数后面加上F或者f,如11.8F
double字面值:小数后面不加F(f)或者小数后面加上D(d),如10.4
double d1 = 123.4;
// same value as d1, but in scientific notation
double d2 = 1.234e2;
float f1 = 123.4f;
字符及字符串字面值
Java 中字符字面值用单引号括起来,如‘@’,‘1’。所有的UTF-16字符集都包含在字符字面值中。
不能直接输入的字符,可以使用转义字符,如\n
为换行字符,也可以使用八进制或者十六进制表示字符,八进制使用反斜杠加3位数字表示,例如\141
表示字母a。十六进制使用\u
加上4为十六进制的数表示,如\u0061
表示字符a。
常见的转义字符序列:\ddd(八进制)
)、\uxxxx(十六进制Unicode字符)
、\'(单引号)
、\"(双引号)
、\\ (反斜杠)
、\r(回车符)
、\n(换行符)
、\f(换页符)
、\t(制表符)
、\b(回格符)
、
字符串字面值则使用双引号,字符串字面值中同样可以包含字符字面值中的转义字符序列。字符串必须位于同一行或者使用+运算符,因为 Java 没有续行转义序列。
基本类型之间的转换
在 Java 中,boolean 类型与所有其他7种类型都不能进行转换。
对于其他7种数值类型,它们之间都可以进行转换,但是可能会存在精度损失或者其他一些变化。
byte <(short=char)< int < long < float < double
如果从小转换到大,可以自动完成,而从大到小,必须强制转换。short 和 char 两种相同类型也必须强制转换。
To\From | byte | short | char | int | long | float | double |
---|---|---|---|---|---|---|---|
byte | - | (byte) | (byte) | (byte) | (byte) | (byte) | (byte) |
short | - | (short) | (short) | (short) | (short) | (short) | |
char | (char) | - | (char) | (char) | (char) | (char) | |
int | - | (int) | (int) | (int) | |||
long | - | (long) | (long) | ||||
float | - | (float) | |||||
double | - |
自动转换
自动转换时发生扩宽(widening conversion)。因为较大的类型(如int)要保存较小的类型(如byte),内存总是足够的,不需要强制转换。如果将字面值保存到 byte、short、char、long 的时候,也会自动进行类型转换。注意区别,此时从 int(没有带L的整型字面值为int)到 byte/short/char 也是自动完成的,虽然它们都比int 小。
在自动类型转化中,除了以下几种情况可能会导致精度损失以外,其他的转换都不能出现精度损失。
- int—> float
- long—> float
- long—> double
- float —>double without strictfp
除了可能的精度损失外,自动转换不会出现任何运行时(run-time)异常。
强制转换
如果要把大的转成小的,或者在 short 与 char 之间进行转换,就必须强制转换。
因为必须显式地使数值更小以适应目标类型。强制转换采用转换操作符()。
// 强制转换格式如下:(target-type) value
int a=257;
byte b;
b = (byte)a;//1
如果整数的值超出了 byte 所能表示的范围,结果将对 byte 类型的范围取余数。
例如a=256超出了byte的[-128,127]的范围,所以将257除以byte的范围(256)取余数得到b=1;需要注意的是,当a=200时,此时除了256取余数应该为-56,而不是200.
将浮点类型赋给整数类型的时候,会发生截尾(truncation)。也就是把小数的部分去掉,只留下整数部分。此时如果整数超出目标类型范围,一样将对目标类型的范围取余数。
赋值及表达式中的类型转换
字面值赋值
在使用字面值对整数赋值的过程中,可以将int literal赋值给byte short char int,只要不超出范围。这个过程中的类型转换时自动完成的,但是如果你试图将long literal赋给byte,即使没有超出范围,也必须进行强制类型转换。例如 byte b = 10L;是错的,要进行强制转换。
表达式中的自动类型提升
除了赋值以外,表达式计算过程中也可能发生一些类型转换。在表达式中,类型提升规则如下:
- 所有byte/short/char都被提升为int。
- 如果有一个操作数为long,整个表达式提升为long。float和double情况也一样。
缓存池
new Integer(123) 与 Integer.valueOf(123) 的区别在于:
- new Integer(123) 每次都会新建一个对象;
- Integer.valueOf(123) 会使用缓存池中的对象,多次调用会取得同一个对象的引用。
- Integer.valueOf(123) 等同于Integer i = 123
valueOf() 方法的实现比较简单,就是先判断值是否在缓存池中,如果在的话就直接返回缓存池的内容,否则创建新对象。Integer x = new Integer(123);
Integer y = new Integer(123);
System.out.println(x == y); // false
Integer z = Integer.valueOf(123);
Integer k = Integer.valueOf(123);
System.out.println(z == k); // true
Integer i = 11;
Integer j = Integer.valueOf(11);
System.out.println(i==j); // true
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
在 Java 8 中,Integer 缓存池的大小默认为 -128~127。
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;
}
编译器会在自动装箱过程调用 valueOf() 方法,因此多个 Integer 实例使用自动装箱来创建并且值相同,那么就会引用相同的对象。
Integer m = 123;
Integer n = 123;
System.out.println(m == n); // true
基本类型对应的缓冲池如下:
- boolean values: true ~ false
- all byte values
- short values: -128 ~ 127
- int values: -128 ~ 127
- char : \u0000 ~ \u007F
在使用这些基本类型对应的包装类型时,就可以直接使用缓冲池中的对象。