Java 一共有多少种数据类型?——从 8 种基本类型到完整 Java 类型体系

本文系统梳理 Java 的完整类型体系,从 **8 种基本数据类型** 出发,进一步介绍类、接口、数组、类型变量以及泛型中的参数化类型、通配符、交叉类型等概念,并解释 `String`、`Integer`、`void`、`var`、`null` 等常见易混点,帮助建立完整、严谨的 Java 类型系统认知。

在学习 Java 时,我们经常会看到一句话:

Java 有 8 种基本数据类型。

这句话本身没有错,但它只回答了“Java 有多少种基本数据类型”,并没有回答“Java 一共有多少种数据类型”。

如果把 Java 的完整类型系统展开,我们会发现:

  • byteintdouble 等只是基本类型;
  • StringStudentArrayList 属于类类型;
  • ListRunnable 属于接口类型;
  • int[]String[] 属于数组类型;
  • 泛型中的 T 属于类型变量;
  • List<String> 属于参数化类型;
  • ? extends NumberNumber & Comparable<?> 等则属于 Java 泛型和类型推导体系中的高级类型结构。

因此,Java 并不存在一个“所有具体类型加起来一共 N 种”的固定答案

原因很简单:程序员可以不断定义新的类、接口、数组组合和泛型类型。

这篇文章将从 Java 语言规范的视角,把 Java 类型体系完整梳理一遍。

一、先给出结论:Java 类型到底有多少种?

如果问题是:

Java 有多少种基本数据类型?

答案是:

8 种。

byte
short
int
long
float
double
char
boolean

如果问题是:

Java 的类型主要分为哪两大类?

最标准的回答是:

Java Type
├── Primitive Type      基本类型
└── Reference Type      引用类型

其中引用类型进一步包括:

Reference Type
├── Class Type          类类型
├── Interface Type      接口类型
├── Type Variable       类型变量
└── Array Type          数组类型

此外,Java 语言中还存在一个特殊的:

null type

但它不是普通意义上可以声明变量的类型,也不应该简单地和基本类型、引用类型并列理解。

所以,真正严谨的结论是:

Java 固定只有 8 种基本类型;引用类型则没有固定数量,因此 Java 的所有具体类型不存在一个固定总数。

二、Java 类型体系总览

先建立整体认识:

Java 类型系统
│
├── 1. Primitive Type 基本类型
│   │
│   ├── Numeric Type 数值类型
│   │   │
│   │   ├── Integral Type 整数类型
│   │   │   ├── byte
│   │   │   ├── short
│   │   │   ├── int
│   │   │   ├── long
│   │   │   └── char
│   │   │
│   │   └── Floating-Point Type 浮点类型
│   │       ├── float
│   │       └── double
│   │
│   └── boolean
│
└── 2. Reference Type 引用类型
    │
    ├── Class Type 类类型
    │   ├── 普通 class
    │   ├── enum
    │   └── record
    │
    ├── Interface Type 接口类型
    │   ├── 普通 interface
    │   └── annotation interface
    │
    ├── Type Variable 类型变量
    │   └── T / E / K / V ...
    │
    └── Array Type 数组类型
        ├── int[]
        ├── String[]
        ├── Student[]
        └── int[][] ...

除此之外,Java 的泛型和类型推导机制中还会出现:

Parameterized Type   参数化类型
Raw Type             原始类型
Wildcard             通配符
Intersection Type    交叉类型
null type            null 的特殊类型

这些概念不能全部简单理解成与 intString 同一级别的“普通数据类型”,但它们共同构成了 Java 完整的类型系统。

三、基本数据类型:固定只有 8 种

Java 的基本类型,也叫:

Primitive Type

它们不是对象,不属于类体系,也不继承 Object

8 种基本类型如下:

| 分类 | 类型 | 位数 | 示例 | | ---- | --------- | -------------------------------------- | ------------------- | | 整数 | byte | 8 | byte a = 10; | | 整数 | short | 16 | short b = 1000; | | 整数 | int | 32 | int c = 100000; | | 整数 | long | 64 | long d = 100L; | | 浮点 | float | 32 | float e = 3.14F; | | 浮点 | double | 64 | double f = 3.14; | | 字符 | char | 16 | char g = 'A'; | | 布尔 | boolean | JVM 规范不按普通整数位宽定义其存储实现 | boolean h = true; |

四、整数类型其实有 5 种

很多教程会说:

整数类型:
byte
short
int
long

从日常编程角度这样说没有问题。

但是从 Java 类型系统角度,char 也属于:

Integral Type

因此更加严谨的分类是:

Integral Type
├── byte
├── short
├── int
├── long
└── char

例如:

char c = 'A';

字符 'A' 对应 Unicode 编码值,因此 char 可以参与部分整数运算。

例如:

char c = 'A';

System.out.println((int) c);

输出:

65

所以 char 虽然通常用于表示字符,但从 Java 语言的类型分类来看,它属于整数类型体系。

五、浮点类型:float 与 double

Java 有两种浮点类型:

float
double

float

float price = 3.14F;

必须注意:

3.14

默认是 double

因此赋值给 float 时通常需要:

3.14F

double

double pi = 3.1415926;

Java 浮点字面量默认就是 double

在一般科学计算和普通业务计算中,double 使用更加广泛。

但是对于金融金额:

double money = 0.1 + 0.2;

可能出现浮点精度问题,因此通常会使用:

BigDecimal

注意:

BigDecimal

不是基本类型,而是一个类。

六、boolean:逻辑类型

Java 中只有一个布尔基本类型:

boolean

只有两个逻辑值:

true
false

例如:

boolean login = true;

if (login) {
    System.out.println("登录成功");
}

与 C 语言不同,Java 不允许直接把整数当作布尔值。

下面代码错误:

int a = 1;

if (a) {
}

Java 要求 if 条件必须最终产生布尔结果。

正确:

if (a != 0) {
}

七、引用类型是什么?

除了 8 种基本类型之外,Java 中大量类型都属于:

Reference Type

例如:

String name = "LingXi";

Student student = new Student();

List<String> list = new ArrayList<>();

int[] numbers = new int[10];

其中:

String
Student
List<String>
ArrayList<String>
int[]

全部属于引用类型体系。

引用变量通常保存的不是对象内容本身,而是对对象的引用。

可以简单理解:

变量
  │
  ↓
引用
  │
  ↓
堆中的对象

例如:

Student student = new Student();

可以抽象理解为:

student
   │
   │ 引用
   ↓
Student 对象

八、类类型:Class Type

最常见的引用类型就是类类型。

例如:

String
Object
Integer
Scanner
ArrayList
Thread
Student
User
Order

假设我们定义:

class Student {

    String name;
    int age;
}

那么:

Student student = new Student();

这里的:

Student

就是一个类类型。

九、普通 class、enum、record 都属于类体系

Java 中的类类型不只是普通 class

还包括一些特殊形式。

普通类

class Student {
}

Student 是类类型。

枚举类型 enum

enum Gender {

    MALE,
    FEMALE
}

可以:

Gender gender = Gender.MALE;

Gender 属于一种特殊的类类型。

记录类型 record

Java 中还可以定义:

record Student(String name, int age) {
}

使用:

Student student = new Student("LingXi", 21);

record 也是一种特殊的类声明形式,其产生的类型仍属于类类型体系。

因此可以这样理解:

Class Type
├── 普通 class
├── enum
└── record

十、接口类型:Interface Type

接口本身也是一种引用类型。

例如:

interface Flyable {

    void fly();
}

定义:

class Bird implements Flyable {

    @Override
    public void fly() {
        System.out.println("Flying...");
    }
}

可以:

Flyable bird = new Bird();

这里:

Flyable

就是接口类型。

Java 标准库中大量类型都是接口,例如:

List
Set
Map
Runnable
Comparable
Serializable
Collection

例如:

List<String> list = new ArrayList<>();

变量声明类型:

List<String>

属于接口类型。

对象实际类型:

ArrayList<String>

属于类类型。

这也是 Java 面向接口编程的重要基础。

十一、注解也是特殊的接口类型

Java 中:

@interface MyAnnotation {
}

定义的是注解类型。

常见注解包括:

@Override
@Deprecated
@SuppressWarnings
@Test

从 Java 类型系统角度,可以把它理解为特殊的接口类型。

因此:

Interface Type
├── 普通 interface
└── annotation interface

十二、数组也是引用类型

这是 Java 初学阶段非常重要的一点:

int 是基本类型,但 int[] 是引用类型。

例如:

int[] numbers = new int[10];

其中:

int

属于:

Primitive Type

但是:

int[]

属于:

Array Type
→ Reference Type

同理:

String[] names;
Student[] students;
int[][] matrix;

全部属于数组类型,也全部属于引用类型。

十三、为什么 Java 的类型总数无法固定?

假设 Java 只有:

int[]

这一种数组类型,那还可以统计。

问题是数组维度可以不断变化:

int[]
int[][]
int[][][]
int[][][][]
...

对象类型也可以不断定义:

class Student {
}

class Teacher {
}

class User {
}

class Order {
}

每定义一个新的类,就产生一个新的类型。

所以:

Java 的所有具体引用类型没有固定数量。

这就是为什么“Java 一共有多少种数据类型”不能简单回答一个数字。

十四、类型变量:Type Variable

泛型出现之后,还需要理解:

Type Variable

例如:

class Box<T> {

    T value;
}

这里的:

T

就是一个类型变量。

它代表:

以后由具体使用者决定这里是什么类型。

例如:

Box<String> box1 = new Box<>();

Box<Integer> box2 = new Box<>();

此时:

T → String

或者:

T → Integer

常见泛型类型变量名称有:

T   Type
E   Element
K   Key
V   Value
R   Result

例如:

Map<K, V>

十五、参数化类型:Parameterized Type

例如:

List<String>
List<Integer>
Map<String, Integer>
Optional<Student>

都属于参数化后的泛型类型。

例如:

List<String> names = new ArrayList<>();

这里可以理解成:

泛型声明:

List<E>

        ↓

把 E 替换为 String

        ↓

List<String>

因此:

List<String>

属于参数化类型。

但是需要注意:

参数化类型并不是 Java 顶层类型分类中新增加的第三大类。

List<String> 本质仍然建立在类或接口类型体系之上。

十六、Raw Type:原始类型

看下面两种写法:

List<String> list = new ArrayList<>();

以及:

List list = new ArrayList();

第二种没有提供泛型参数:

List

这叫:

Raw Type
原始类型

Raw Type 主要用于兼容 Java 5 引入泛型之前的旧代码。

现代 Java 开发中通常不建议使用。

因为它会失去泛型提供的编译期类型安全。

例如:

List list = new ArrayList();

list.add("Hello");
list.add(100);
list.add(new Student());

编译器很难提供严格的元素类型约束。

而:

List<String> list = new ArrayList<>();

只能正常添加字符串:

list.add("Hello");

下面会直接编译错误:

list.add(100);

十七、Wildcard:泛型通配符

Java 泛型中还有:

?
? extends T
? super T

例如:

List<?> list;

表示:

一个元素具体类型未知的 List。

再例如:

List<? extends Number>

表示:

List 中元素类型是 Number 或 Number 的某个子类型。

例如可能是:

List<Integer>
List<Double>
List<Long>

再例如:

List<? super Integer>

表示:

元素类型是 Integer 或 Integer 的某个父类型。

泛型中经常会提到:

PECS

即:

Producer Extends
Consumer Super

简单理解:

读取数据为主:
? extends T

写入数据为主:
? super T

这是 Java 泛型中非常重要的知识点。

十八、Intersection Type:交叉类型

Java 还存在:

Intersection Type

即:

A & B

表示一个类型必须同时满足多个约束。

例如:

<T extends Number & Comparable<T>>

其中:

Number & Comparable<T>

就是交叉类型结构。

意思是:

T 必须:

是 Number 的子类型

并且

实现 Comparable<T>

例如:

public static <T extends Number & Comparable<T>>
void print(T value) {

    System.out.println(value);
}

交叉类型还可能出现在强制类型转换中:

(Runnable & java.io.Serializable) () -> {
    System.out.println("Hello");
};

这里要求 Lambda 对象同时满足:

Runnable
+
Serializable

十九、null 是什么类型?

这是 Java 类型系统中很容易被忽略的一个特殊概念。

例如:

String name = null;

Student student = null;

Object object = null;

为什么 null 可以赋值给不同的引用类型?

因为 Java 语言中存在一个特殊的:

null type

它唯一对应的值就是:

null

但是不能写:

null value;

因为:

null

不是一个可以直接作为类型名称使用的关键字类型。

所以更加准确地说:

null 是空引用字面量,它具有一个特殊的 null type,并可以转换成引用类型。

二十、基本类型与引用类型最核心的区别

例如:

int a = 10;

和:

Student student = new Student();

虽然都叫“变量”,但两者属于完全不同的类型体系。

可以粗略理解:

基本类型变量

a
↓
10

而引用类型:

student
   │
   ↓
对象引用
   │
   ↓
Student 对象

常见区别如下:

| 对比项 | 基本类型 | 引用类型 | | --------------- | -------------- | ---------------------- | | 示例 | int | String | | 是否对象 | 否 | 通常用于引用对象/数组 | | 是否继承 Object | 否 | 类和数组等进入引用体系 | | 默认值 | 0false等 | null | | 能否为 null | 不能 | 可以 | | 泛型中直接使用 | 不能 | 可以 |

例如:

List<int> list;

错误。

必须:

List<Integer> list;

因为 Java 泛型使用的是引用类型体系。

二十一、包装类不是基本类型

Java 为 8 种基本类型分别提供了包装类。

| 基本类型 | 包装类 | | --------- | ----------- | | byte | Byte | | short | Short | | int | Integer | | long | Long | | float | Float | | double | Double | | char | Character | | boolean | Boolean |

例如:

int age = 21;

Integer boxedAge = 21;

这两个类型完全不同。

int
↓
Primitive Type

而:

Integer
↓
Class Type
↓
Reference Type

Java 可以通过:

Autoboxing
自动装箱

自动完成:

Integer a = 10;

逻辑上相当于把:

int

包装成:

Integer

反过来则叫:

Unboxing
自动拆箱

例如:

Integer a = 10;

int b = a;

二十二、String 到底是什么类型?

很多 Java 初学者会产生疑问:

String name = "LingXi";

看起来和:

int age = 21;

非常像。

于是容易误认为:

String 是一种基本数据类型

这是错误的。

String 的真实身份是:

java.lang.String
↓
Class Type
↓
Reference Type

也就是说:

String 是 Java 提供的一个类。

只不过 Java 对字符串字面量提供了非常方便的语法:

String name = "LingXi";

所以使用体验看起来很像基本类型。

二十三、Object 是所有类型的父类吗?

经常看到一句话:

Object 是 Java 所有类型的父类。

这句话也需要修正。

更加准确的是:

Object 是 Java 类层次结构中的根类,大多数对象最终都属于 Object 体系。

例如:

Object
↑
String
Integer
Student
ArrayList
Thread
...

但是:

int
double
boolean
char

这些基本类型不是类。

所以:

int

并不继承:

Object

例如:

int a = 10;

这里 a 不是对象。

但是自动装箱之后:

Integer a = 10;

此时:

Integer
↓
Number
↓
Object

就进入了对象类型体系。

二十四、void 是不是第 9 种基本数据类型?

不是。

有些旧教程会把:

void

和 8 种基本类型放在一起。

例如:

public void test() {

}

这里:

void

表示:

这个方法不返回任何值。

但是不能:

void value;

因此:

void 不属于 Java 的 8 种基本数据类型。

学习时最好不要背:

Java 有 9 种基本类型,包括 void

正确答案始终是:

8 种基本类型

二十五、var 是不是一种数据类型?

也不是。

Java 10 引入了局部变量类型推断:

var name = "LingXi";

编译器会推断:

name 的类型是 String

等价理解:

String name = "LingXi";

再例如:

var age = 21;

编译器推断:

int

再例如:

var list = new ArrayList<String>();

推断为:

ArrayList<String>

所以:

var

不是数据类型。

它只是:

局部变量类型推断语法

二十六、为什么泛型不能直接使用 int?

例如:

List<int> numbers;

会编译失败。

因为 Java 泛型的类型参数要求使用引用类型。

所以必须写:

List<Integer> numbers;

Java 会通过自动装箱,把:

int

转换为:

Integer

例如:

List<Integer> numbers = new ArrayList<>();

numbers.add(10);

实际上这里发生了:

10
↓
int
↓
自动装箱
↓
Integer

这也是理解基本类型与引用类型区别之后非常自然的一个结论。

二十七、为什么 Java 类型没有固定总数?

现在可以回答最开始的问题。

Java 固定的基本类型只有:

8 种

但是程序员可以不断创建:

class Student {
}

class Teacher {
}

class User {
}

class Order {
}

class Product {
}

于是:

Student
Teacher
User
Order
Product

全部成为新的类型。

还可以产生:

Student[]
Student[][]
List<Student>
Map<String, Student>
Optional<Student>

所以 Java 的具体类型数量理论上可以不断增加。

因此不能说:

Java 一共有 8 种数据类型

更加准确的说法应该是:

Java 一共有 8 种基本数据类型,而引用类型没有固定数量。

二十八、完整 Java 类型知识结构

最后把整个知识体系整理成一棵树:

Java Type System
│
├── Primitive Type
│   │
│   ├── Numeric Type
│   │   │
│   │   ├── Integral Type
│   │   │   ├── byte
│   │   │   ├── short
│   │   │   ├── int
│   │   │   ├── long
│   │   │   └── char
│   │   │
│   │   └── Floating-Point Type
│   │       ├── float
│   │       └── double
│   │
│   └── boolean
│
└── Reference Type
    │
    ├── Class Type
    │   ├── 普通 class
    │   ├── enum
    │   └── record
    │
    ├── Interface Type
    │   ├── interface
    │   └── annotation interface
    │
    ├── Type Variable
    │   └── T / E / K / V ...
    │
    └── Array Type
        ├── int[]
        ├── String[]
        ├── Student[]
        └── int[][] ...

围绕这套核心类型系统,还会出现:

Parameterized Type
Raw Type
Wildcard
Intersection Type
null type

它们主要出现在:

泛型
类型推导
类型转换
编译器类型检查

等更加高级的 Java 场景中。

二十九、考试、面试应该怎么回答?

不同问题,要给不同层级的答案。

问:Java 有多少种基本数据类型?

回答:

Java 有 8 种基本数据类型:byteshortintlongfloatdoublecharboolean

问:Java 数据类型分为哪两大类?

回答:

Java 类型主要分为基本类型和引用类型。

Primitive Type
Reference Type

问:Java 的引用类型有哪些?

回答:

Java 引用类型主要包括类类型、接口类型、类型变量和数组类型。

Class Type
Interface Type
Type Variable
Array Type

问:String 是基本类型吗?

回答:

不是。Stringjava.lang.String 类,因此属于引用类型中的类类型。

问:数组是基本类型还是引用类型?

回答:

数组属于引用类型。即使数组元素是 intint[] 本身依然是引用类型。

问:Integer 是基本类型吗?

回答:

不是。Integerint 对应的包装类,属于类类型。

问:void 是基本类型吗?

回答:

不是。void 用于表示方法没有返回值,不属于 Java 的 8 种基本类型。

问:var 是类型吗?

回答:

不是。var 是局部变量类型推断语法,变量最终仍然拥有具体的静态类型。

三十、最终总结

如果只记一句话:

Java 固定只有 8 种基本数据类型,但 Java 的所有具体类型没有固定总数量。

8 种基本类型:

byte
short
int
long
float
double
char
boolean

Java 类型体系最核心的结构:

Java Type
├── Primitive Type
└── Reference Type

引用类型主要包括:

Class Type
Interface Type
Type Variable
Array Type

除此之外,还应该理解:

Parameterized Type
Raw Type
Wildcard
Intersection Type
null type

最终真正需要建立的思维不是:

Java = 背 8 个数据类型

而是:

Java 类型系统
      │
      ├── 基本值
      │
      ├── 对象
      │
      ├── 接口抽象
      │
      ├── 数组
      │
      ├── 泛型
      │
      └── 编译器类型约束

当这套类型体系真正建立起来之后,后续学习:

面向对象
集合框架
泛型
反射
Lambda
Stream
Java API
Spring

都会更加自然。

因为它们本质上都建立在 Java 的类型系统之上。