基本类型 大小 最小值 最大值 字段默认值 包装器类型
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表示。 赋值可能是这样的:

  1. char ch1 = 88;
  2. char ch2 = 'A';
  3. char ch3 = '汉';

ASCII字符集占用了Unicode的前127个值。之所以把char归入整型,是因为Java为char提供算术运算支持,例如可以ch2++;之后ch2就变成Y。当char进行加减乘除运算的时候,也被转换成int类型,必须显式转化回来。

整型

byte

byte 由1个字节8位表示,是最小的整数类型。主要用于节省内存空间关键。
当操作来自网络、文件或者其他 IO 的数据流时,byte类型特别有用。

  1. // byte常见问题
  2. public void test(byte b);
  3. test(0); // 编译器报错,类型不兼容

对byte类型进行数学运算时,会自动提升为int类型,如果表达式中有double或者float等类型,也是自动提升。

  1. byte s1 = 100;
  2. byte s2 = 'a';
  3. // 下列代码是错误的:
  4. byte sum = s1 + s2;//should cast by (byte)

short

short可能是最不常用的类型了。可以通过整型字面值或者字符字面值赋值,前提是不超出范围(16 bit)。
short类型参与运算的时候,一样被提升为int或者更高的类型。(顺序为 byte short int long float double).

  1. //由于 1 是 int 类型,因此 s1+1 运算结果也是 int型,需要强制转换类型才能赋值给 short 型。
  2. short s1 = 1; s1 = s1 + 1 ;// 编译错误
  3. //s1+= 1;相当于 s1 = (short(s1 + 1);其中有隐含的强制类型转换。
  4. 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更快,占内存更小,但是当数值非常大或者非常小的时候会变得不精确。

  1. // 精度要求不高的时候可以使用float类型,声明赋值示例:
  2. float f1 =10;
  3. f1 = 10L;
  4. 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 和更高版本创建二进制字面值)
  1. 使用的语法:
  2. // The number 26, in decimal
  3. int decVal = 26;
  4. // The number 26, in hexadecimal
  5. int hexVal = 0x1a;
  6. // The number 26, in binary
  7. int binVal = 0b11010;

浮点字面值

浮点字面值简单的理解可以理解为小数。分为float字面值和double字面值
float字面值:在小数后面加上F或者f,如11.8F
double字面值:小数后面不加F(f)或者小数后面加上D(d),如10.4

  1. double d1 = 123.4;
  2. // same value as d1, but in scientific notation
  3. double d2 = 1.234e2;
  4. 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种数值类型,它们之间都可以进行转换,但是可能会存在精度损失或者其他一些变化。

  1. 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 之间进行转换,就必须强制转换。
因为必须显式地使数值更小以适应目标类型。强制转换采用转换操作符()。

  1. // 强制转换格式如下:(target-type) value
  2. int a=257;
  3. byte b;
  4. 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
    1. Integer x = new Integer(123);
    2. Integer y = new Integer(123);
    3. System.out.println(x == y); // false
    4. Integer z = Integer.valueOf(123);
    5. Integer k = Integer.valueOf(123);
    6. System.out.println(z == k); // true
    7. Integer i = 11;
    8. Integer j = Integer.valueOf(11);
    9. System.out.println(i==j); // true
    valueOf() 方法的实现比较简单,就是先判断值是否在缓存池中,如果在的话就直接返回缓存池的内容,否则创建新对象。
    1. public static Integer valueOf(int i) {
    2. if (i >= IntegerCache.low && i <= IntegerCache.high)
    3. return IntegerCache.cache[i + (-IntegerCache.low)];
    4. return new Integer(i);
    5. }

在 Java 8 中,Integer 缓存池的大小默认为 -128~127

  1. static final int low = -128;
  2. static final int high;
  3. static final Integer cache[];
  4. static {
  5. // high value may be configured by property
  6. int h = 127;
  7. String integerCacheHighPropValue =
  8. sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
  9. if (integerCacheHighPropValue != null) {
  10. try {
  11. int i = parseInt(integerCacheHighPropValue);
  12. i = Math.max(i, 127);
  13. // Maximum array size is Integer.MAX_VALUE
  14. h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
  15. } catch( NumberFormatException nfe) {
  16. // If the property cannot be parsed into an int, ignore it.
  17. }
  18. }
  19. high = h;
  20. cache = new Integer[(high - low) + 1];
  21. int j = low;
  22. for(int k = 0; k < cache.length; k++)
  23. cache[k] = new Integer(j++);
  24. // range [-128, 127] must be interned (JLS7 5.1.7)
  25. assert IntegerCache.high >= 127;
  26. }

编译器会在自动装箱过程调用 valueOf() 方法,因此多个 Integer 实例使用自动装箱来创建并且值相同,那么就会引用相同的对象。

  1. Integer m = 123;
  2. Integer n = 123;
  3. System.out.println(m == n); // true

基本类型对应的缓冲池如下:

  • boolean values: true ~ false
  • all byte values
  • short values: -128 ~ 127
  • int values: -128 ~ 127
  • char : \u0000 ~ \u007F

在使用这些基本类型对应的包装类型时,就可以直接使用缓冲池中的对象