Skip to content
目录概览

数据类型

Java 的数据类型分为:布尔(boolean)类型、字符类型和数值类型,其中数值类型又可以细分为:整数类型 和 浮点类型;

基本
类型
包装类
字节数
位数
最小值
最大值
默认值
byteByte18-2^7(-128)2^7 - 1(127)(byte)0
shortShort216-2^152^15 - 1(short)0
intInteger432-2^312^31 - 10
longLong864-2^632^63 - 10L
floatFloat4321.4E - 4
(2^-149)
3.4028235E38
(2^128 - 1)
0.0f
doubleDouble8644.9E - 324
(2^-1074)
1.7976931348623157E308(2^1024-1)0.0d
charCharacter216\u0000\uFFFF'/uoooo'(null)
booleanBoolean180(false)1(true)false

基本数据类型声明

java
byte byteData;
short shortData;
int intData;
long longData;
float floatData;
double doubleData;
char charData;
boolean booleanData;

byte

一个byte类型整数在内存里占8位,表数范围是 -128(-2^7)127(2^7-1)

特点:空间占用小,仅为 int 类型的1/4

java
byte a = -128;
byte b = 127;

short

一个 short 类型整数在内存里占 16 位,表数范围是 -32768(-2^15)32767(2^15-1)

特点:空间占用较小,仅为 int 类型的 1/2

java
short a = -32768;
short b = 32767;

int

一个 int 类型整数在内存里占 32 位,取值范围是 -2147483648(-2^31)2147483647(2^31-1)

特点:int 是最常用的整数类型,默认情况下,给一个整数,默认就是 int 类型,如果数值比较小,然后用 byte 或者 short 赋值,系统就会整数当作 byte 或者 short 来处理;

java
int min = -2147483648;
Integer max = 2147483647;
System.out.println(min);
System.out.println(max);
System.out.println(Integer.MIN_VALUE);
System.out.println(Integer.MAX_VALUE);

输出:

-2147483648

2147483647

-2147483648

2147483647

long

一个 long 类型整数在内存里占64位,表数范围是 -9223372036854774808(-2^63)9223372036854774807(2^63-1)

默认情况下,系统会将数值当作 int 来处理,当数超过了 int 的表示范围,系统并不会自动转换为 long 型,因此,如果需要一个 long 类型的数值,可以在数值后面添加一个l或者L后缀(l容易和1混淆,所以一般都使用L作为后缀)

java
long min = -9223372036854774808L;
Long max = 9223372036854775807L;
System.out.println(min);
System.out.println(max);
System.out.println(Long.MIN_VALUE);
System.out.println(Long.MAX_VALUE);

输出:

-9223372036854774808

9223372036854775807

-9223372036854774808

9223372036854775807

浮点数

Java使用IEEE 754浮点标准存储实数。支持两种浮点类型,分别是:float型、double型。

浮点表示法,分为三大部分:

  • 第一部分用来存储符号位(sign)占用1位,用来表示正负数;

  • 第二部分用来存储指数(exponent);

  • 第三部分用来存储尾数(mantissa)。

float

float 用来表示单精度浮点数,内存分配 4 个字节,占 32 位,取值范围在 2^-1492^128 - 1;指数占用 8 位,位数占用 23 位,用来表示小数,不足位数补 0;

Java 定义float类型时,可以在数值类型后面添加f或F后缀;

java
float min = 1.4E-45F;
Float max = 3.4028235E38F;
System.out.println(min);
System.out.println(max);
System.out.println(Float.MIN_VALUE);
System.out.println(Float.MAX_VALUE);

输出:

1.4E-45

3.4028235E38

1.4E-45

3.4028235E38

double

double 用来表示双精度浮点数,内存分配 8 个字节,占 64 位,取值范围在 2^-10742^1024-1;指数占用 11 位,位数占用 52 位,用来表示小数,不足位数补 0;

java
double min = 4.9E-324D;
Double max = 1.7976931348623157E308D;
System.out.println(min);
System.out.println(max);
System.out.println(Double.MIN_VALUE);
System.out.println(Double.MAX_VALUE);

输出:

4.9E-324

1.7976931348623157E308

4.9E-324

1.7976931348623157E308

char

字符型数据类型;用于存放单个字符。定义的时候使用单引号(' ')表示;char在 Java 中是 16 位,因为 Java 用的是 Unicode ,因此一个 16 位的编码所能产生的字符只有65536个。

中文Unicode对照表

在线中文与Unicode转换工具

java
char a = '\u4e00'; // 一
System.out.println(a); // 一
char[] b = {'\u4e00', '\u884c', '\u004a', '\u0061', '\u0076', '\u0061'}; // 一行Java 的Unicode 编码
System.out.println(b); // 一行Java
System.out.println(new String(b)); // 一行Java

输出:

一行Java

一行Java

boolean

boolean 是只具有两个值的的数据类型,用来表示逻辑判断的真与假;Java 中 boolean 的值为 true 或 false

java
boolean t = Boolean.TRUE;
Boolean f = Boolean.FALSE;
System.out.println(t);
System.out.println(f);
System.out.println(1 > 2);
System.out.println(1 > 0);

输出:

true

false

false

true

基本类型转换

Java 的7种不同数据类型的值之间,是可以进行转换的;实际开发过程中,这种转换也经常会遇到;

在 Java 程序中,类型转换的方式有两种:

  • 自动类型转换
  • 强制类型转换

自动类型转换

上面我们学习过不同的数据类型,每种不同类型的值所表示的范围是不一样的,如果将一个表示范围小的值赋给一个表示范围更大的类型,系统就能直接进行自动转换;

好比将一个小号杯子中的水倒入到一个大杯中,小杯中的水都能够正常装入到大的杯子,也不会洒出来;

以下是支持自动转换的顺序:

  • 基本数据类型的自动转换

    java
    byte a = 10;
    int b = a;
    long c = a;
    
    System.out.println(b); // 10
    System.out.println(c); // 10
  • 字符串类型的自动转换

    示例可以看出,当一个基本数据类型和一个String类型相加时,系统会将基本数据类型自动转换为字符串类型进行拼接;

    java
    byte a = 10;
    int b = a;
    String d = "一行Java" + b;
    
    System.out.println(b); // 10
    System.out.println(d); // 一行Java10

强制类型转换

如果将上面自动类型转换的顺序反过来,也就相当于将大杯中的水往小杯中倒时,就需要进行强制转换;如果本身的值超过了转后类型的取值范围,就会产生溢出,造成数据丢失;

  • 基本数据类型的强转

    java
    int a1 = 50;
    // int 的值没有超出byte的取值范围,强转之后,不会出现数据丢失
    byte b1 = (byte) a1;
    System.out.println(b1); // 50
    
    // 以下是超出取值范围的情况
    
    // 转换之后符号位为负数的情况
    int a2 = 500;
    byte b2 = (byte) a2;
    System.out.println(b2); // -12
    
    // 转换之后符号位为正数的情况
    int a3 = 865;
    byte b3 = (byte) a3;
    System.out.println(b3); // 97

    以下是500865的强转过程:

  • 字符串转换

    上面介绍自动转换时,基本数据类型和字符串类型拼接的时候,会自动将基本数据类型转换为字符串类型,但字符串类型是没办法强制转换为基本数据类型;

    java
    // 以下代码是会报错的
    int a = (int)"1";

    因此,只能借助基础类型包装类中的valueOf方法,将字符串转换为基础数据类型

    java
    System.out.println(Byte.valueOf("10"));  //10
    System.out.println(Short.valueOf("100"));  //100
    System.out.println(Integer.valueOf("1000"));  //1000
    System.out.println(Long.valueOf("100000000000000000"));  //100000000000000000
    System.out.println(Float.valueOf("1.23"));  //1.23
    System.out.println(Double.valueOf("4.56"));  //4.56
    System.out.println(Boolean.valueOf("true"));  //true

    如果出现不符合转换要求的字符串或者超过取值范围的字符串,就会报转换错误:

    java
    System.out.println(Byte.valueOf("一行Java"));
    
    // 异常如下
    Exception in thread "main" java.lang.NumberFormatException: For input string: "一行Java"
    	at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
    	at java.base/java.lang.Integer.parseInt(Integer.java:652)
    	at java.base/java.lang.Byte.parseByte(Byte.java:152)
    	at java.base/java.lang.Byte.valueOf(Byte.java:208)
    	at java.base/java.lang.Byte.valueOf(Byte.java:234)
    	at main.DataType.main(DataType.java:12)
    java
    System.out.println(Byte.valueOf("1000"));
    
    // 异常如下
    Exception in thread "main" java.lang.NumberFormatException: Value out of range. Value:"1000" Radix:10
    	at java.base/java.lang.Byte.parseByte(Byte.java:154)
    	at java.base/java.lang.Byte.valueOf(Byte.java:208)
    	at java.base/java.lang.Byte.valueOf(Byte.java:234)
    	at main.DataType.main(DataType.java:12)

表达式的类型提升

当出现多个类型的值参与运算时,会出现类型的提升的情况

  • 当byte、short、char 参与运算时,会自动将类型提升为 int

    以下示例中将byte的a加2时,a被提升为了 int,将计算结果再赋值给 byte 类型的a时,就会报错了

    java
    byte a = 2;
    // 由于运算的过程中,a被自动提升为int,计算出来的结果也就是int类型
    // 再将一个int类型的值赋值给byte类型的a,就会报错
    a = a + 2;
    
    // 如果想不报错,只能做强制类型转换,或者用int接收
    a = (byte)(a + 2);
    // 或者
    int b = a + 2;
  • 算术表达式的所有类型将自动提升为参与表达式的最高类型,类型提升顺序请参考

    当表达式中有多个数据类型时,会将低类型的数据提升为最高类型的数据进行运算;

    以下示例,由于最高类型是float,将所有元素全部提升为 float 参与运算,得到的结果也就是 float 类型

    java
    byte a = 1;
    int b = 2;
    float c = 3.1F;
    float d = a + b + c;
    System.out.println(d); // 6.1

    以下示例,哪怕3/2 正确结果应该是double类型的 1.5 ,但由于表达式中最高类型为 int,使得数据强转丢失,导致计算出来的结果为 int 类型的1

    java
    int a = 3;
    int b = a/2; //1

基础类型和包装类型的区别

基础数据类型都会对应一个包装类,那他们之间有些什么区别呢?

  1. 包装类是对象,拥有方法和字段,对象的调用都是通过引用对象的地址;基本类型不是
  2. 包装类型是引用的传递;基本类型是值的传递
  3. 声明方式不同:
    • 基本数据类型不需要new关键字,直接赋值,如:int a = 10;
    • 包装类型需要new在堆内存中进行new来分配内存空间,如:Integer a = new Integer(10);
  4. 存储位置不同:
    • 基本数据类型直接将值保存在值栈中;
    • 包装类型是把对象放在堆中,然后通过对象的引用来调用他们
  5. 初始值不同:
    • 基础数据类型会赋对应类型的初始值,

      如:int初始值为:0

      boolean的初始值为:false

      double初始值为:0.0

    • 包装类型的初始值为null
  6. 使用方式不同:
    • 基本数据类型直接赋值使用就好;
    • 包装类型一般可以放在集合中使用,如 Collection集合中List、Set,以及Map键值对存储。

什么是装箱和拆箱?

  • 装箱

    就是自动将基本数据类型转换为包装器类型;原理是调用包装类的valueOf方法,如:Integer.valueOf(1)Boolean.valueOf(true)...

  • 拆箱

    就是自动将包装器类型转换为基本数据类型;原理是是调用包装类的xxxValue方法(xxx表示类型),如:

    java
    public boolean booleanValue() {
        return value;
    }