ITPub博客

首页 > 应用开发 > Java > Java中的数据类型

Java中的数据类型

原创 Java 作者:mxrpz196 时间:2026-02-02 13:41:29 0 删除 编辑

Java 数据类型详解

目录


数据类型分类

Java 数据类型
├── 基本类型(8种)
│   ├── 整数类型:byte, short, int, long│   ├── 浮点类型:float, double│   ├── 字符类型:char│   └── 布尔类型:boolean└── 引用类型
    ├── 类(如 String)
    ├── 接口
    └── 数组

基本数据类型

整数类型

类型 位数 范围 默认值 示例
byte 8位 -128 ~ 127 0 byte b = 100;
short 16位 -32,768 ~ 32,767 0 short s = 10000;
int 32位 -21亿 ~ 21亿 0 int i = 100000;
long 64位 极大 0L long l = 100000L;
byte  a = 127;     // ✅ 最大值// byte b = 128;  // ❌ 超出范围int   c = 100;long  d = 100000L; // long 需加 L 或 llong  e = 10000000000L; // ✅ 超出int范围必须加L// long  f = 10000000000; // ❌ 编译错误,超出 int 范围

浮点类型

类型 位数 精度 默认值 示例
float 32位 单精度(7位有效数字) 0.0f float f = 3.14f;
double 64位 双精度(15位有效数字) 0.0 double d = 3.14;
double a = 3.14;     // 默认是 double// float b = 3.14;  // ❌ 编译错误float  c = 3.14f;    // ✅

字符类型

类型 位数 说明 默认值 示例
char 16位 单个 Unicode 字符 \u0000 char c = 'A';
char a = 'A';       // 字符char b = '中';      // 中文char c = 65;        // 数字对应字符 'A'char d = '\u0041';  // Unicode 转义,'A'char e = '\u0000';  // null 字符,char 的默认值// char f = 'AB';  // ❌ char 只能存单个字符

布尔类型

类型 取值 默认值 示例
boolean true, false false boolean flag = true;
boolean a = true;boolean b = false;

引用类型

什么是引用类型

引用类型存储的是对象的地址(引用),对象本身存储在堆中。

常见引用类型

类型 说明 示例
String 字符串类 String s = "hello";
数组 数组 int[] arr = {1, 2, 3};
接口 接口类型 List<String> list;
自定义类 用户定义的类 Person p = new Person();

基本类型 vs 引用类型

对比维度 基本类型 引用类型(如 String)
存储位置 栈中,直接存值 栈存引用,堆存对象
大小 固定(如 int 4字节) 不固定
默认值 0/false/\u0000 null
比较 == 比较值 == 比较地址, equals() 比较内容

内存图示

基本类型:
栈
┌─────────┐
│ int a   │ = 10└─────────┘
  直接存值
引用类型:
栈                    堆
┌─────────┐          ┌─────────┐
│String s │ ────────→│ "hello" │
└─────────┘          └─────────┘
 引用变量            实际对象

比较示例

// 基本类型int a = 10;int b = 10;
System.out.println(a == b);  // true(比较值)// 引用类型String s1 = new String("hello");String s2 = new yccgc.cn String("hello");
System.out.println(s1 == s2);         // false(不同地址)System.out.println(s1.equals(s2));    // true(内容相同)

包装类

每个基本类型都有对应的包装类:

基本类型 包装类 说明
byte Byte
short Short
int Integer
long Long
float Float
double Double
char Character
boolean Boolean
int a = 10;              // 基本类型Integer b = 10;          // 包装类Integer c = Integer.valueOf(10); // 显式创建// 自动装箱/拆箱Integer d = a;           // 自动装箱int e = d;               // 自动拆箱

String 详解

String 是什么?

String 是类,不是基本类型,是不可变的引用类型。

String 的不可变性

String a = "hello";String b = a;              // a 和 b 指向同一对象a = "world";               // a 指向新对象System.out.println(b);     // 输出: hello(b 不变) www.yccgc.cn System.out.println(a == b); // false(已不是同一对象)
内存变化:
修改前:a ──→ ["hello"]
      ↑      b修改后:a ──→ ["world"]  ← 新对象b ──→ ["hello"]  ← 原对象不变

为什么 String 不可变?

// String 简化版源码public final class String {    private final char value[];  // final,不能修改
    // 所有修改操作都返回新 String
    public String substring(int beginIndex) {        return new String(value, beginIndex, count);
    }
}
原因 说明
不可变 String 对象一旦创建,内容不能改
final String 类内部用 final 修饰字符数组
安全 多线程环境下,无需加锁就能安全共享

String vs 可变对象

// String - 不可变String a = "hello";String b = a;
a = "world";
System.out.println(b);  // hello(不变)// StringBuilder - 可变StringBuilder sb1 = new StringBuilder("hello");String wap.yccgc.cn Builder sb2 = sb1;
sb1.append(" world");
System.out.println(sb2);  // hello world(变了!)

字符串常量池

什么是字符串常量池

┌─────────────────────────────────────────────────────┐
│                   字符串常量池                       │
│  (JVM 堆内存中的一块特殊区域,专门存储字符串字面量)  │
│                                                     │
│   "hello"                                           │
│   "world"                                           │
│   "java"                                            │
└─────────────────────────────────────────────────────┘

字面量 vs new

方式 写法 存储位置 是否复用
隐式(字面量) String s = "hello"; 字符串常量池 ✅ 复用
显式(new) String s = new String("hello"); 堆内存(新对象) ❌ 新对象
动态创建 scanner.nextLine() 堆内存(新对象) ❌ 新对象

字面量(隐式赋值)

String a = "hello";String b = "hello";

流程:

  1. JVM 检查常量池中是否有  "hello"
  2. 有 → 直接引用(复用)
  3. 无 → 在常量池创建  "hello",然后引用
常量池:
┌─────────┐
│ "hello" │ ← a ─┐
└─────────┘       │
                  │ 两者指向同一对象
                  ├─ b
System.out.println(a == b);  // true(同一对象)

new(显式赋值)

String c = new String("hello");String d = new String("hello");

流程:

  1. 先在常量池检查/创建  "hello"
  2. 然后在堆内存 强制创建新对象
  3. 变量引用堆上的新对象(不是常量池)
常量池:            堆内存:
┌─────────┐        ┌─────────┐
│ "hello" │ ───→   │ "hello" │ ← c
└─────────┘        └─────────┘
                   ┌─────────┐
                   │ "hello" │ ← d
                   └─────────┘
System.out.println(c == d);   // false(不同对象)System.out.println(c == a);   // false(c 在堆,a 在常量池)System.out.println(c.equals(a)); // true(值相同)

scanner 输入

String c = scanner.nextLine(); // 输入: helloString d = scanner.nextLine(); // 输入: helloSystem.out.println(c == d);    // false(每次新对象)

内存布局

Java 版本差异

版本 常量池位置
Java 6 及之前 方法区(代 PermGen)
Java 7+ 堆
Java 8+ 堆(方法区改为元空间 Metaspace)

现代 Java(7+):字符串常量池在堆上。

完整内存布局

String s1 = "first";String s2 = new String("second");
栈:
┌─────────┐      ┌─────────┐
│   s1    │      │   s2    │
└─────────┘      └─────────┘
  ↓ 引用            ↓ 引用
堆(都在堆上):
┌───────────────────────────────────────────────────┐
│                                                   │
│  常量池区域:         普通堆区域:                  │
│  ┌─────────┐        ┌─────────────────────┐       │
│  │ "first" │        │ String对象           │       │
│  │"second" │        │ value → "second"    │       │
│  └─────────┘        └─────────────────────┘       │
│                             ↓                      │
│                     ┌─────────┐                   │
│                     │"second" │ ← 在常量池         │
│                     └─────────┘                   │
│                                                   │
└───────────────────────────────────────────────────┘

new String("xxx") 的步骤

1. 先处理 "xxx" 字面量
   → 检查常量池有没有 "xxx"
   → 没有 → 在常量池创建 "xxx"
   → 有 → 复用2. 再执行 new String()
   → 在普通堆创建新对象
   → 对象内部引用常量池的 "xxx"
String s = new String("second");// 等价于:String literal = "second";      // 先处理字面量,进常量池String s = new String(literal); // 再创建堆对象

对象生命周期

对象的一生

┌─────────────────────────────────────────────────────────┐
│                   对象一生                               │
├─────────────────────────────────────────────────────────┤
│                                                         │
│  1. 创建     →  new String() / scanner.nextLine()      │
│     ↓                                                  │
│  2. 使用     →  被变量引用,可以访问                    │
│     ↓                                                  │
│  3. 失去引用 →  变量指向其他对象或离开作用域            │
│     ↓                                                  │
│  4. 可回收    →  等待 GC 清理                          │
│     ↓                                                  │
│  5. 回收     →  GC 自动回收内存                        │
│                                                         │
└─────────────────────────────────────────────────────────┘

示例:引用丢失

String s1 = scanner.nextLine();  // 创建对象s1 = scanner.nextLine();         // s1 指向新对象,原对象可被回收

垃圾回收(GC)

GC = Garbage Collection,Java 自动内存管理机制。

GC 工作原理:1. 定期扫描堆内存2. 找出没有被引用的对象3. 回收内存

不同区域的回收策略

类型 生命周期 回收方式
字面量(常量池) 程序运行期间 一般不回收
动态对象(堆) 到无引用时 GC 回收
基础类型(栈) 作用域内 自动销毁
String a = "hello";  // 常量池,程序运行期间存在String b = scanner.nextLine();  // 堆对象b = null;  // 失去引用,等待 GC

intern() 方法

将字符串内容放入常量池。

String s = new String("aaa");
s.intern();  // 将 "aaa" 内容放入常量池(如果还没)
String s1 = new String("aaa");String s2 = new String("aaa");String s3 = "aaa";  // 字面量,常量池String s4 = s1.intern();  // 返回常量池中的引用System.out.println(s1 == s2);   // false(堆对象,不同)System.out.println(s1 == s3);   // false(堆 vs 常量池)System.out.println(s3 m.yccgc.cn == s4);   // true(都是常量池)

常见问题

Q1: \u0000 是什么?

\u0000 是 Unicode 字符的转义表示,表示 Unicode 值为 0 的字符。

方面 说明
Unicode 值 0
名称 null 字符 / 空字符
可见性 不可见(控制字符)
Java 中 char 的默认值
char c = '\u0000';          // null 字符char d = 0;                 // 等价写法System.out.println(c == d); // trueSystem.out.println((int)c); // 输出: 0

Q2: String 引用相同但值不同?

对于 String,不可能。

String a = "hello";String b = a;
a = "world";
System.out.println(b);  // hello(b 不变)

核心原因: String 是不可变的,引用相同则值必相同。

Q3: scanner.nextLine() 返回什么?

永远返回 String,无论输入什么。

Scanner scanner = new Scanner(System.in);String input = scanner.nextLine();  // 输入 27 → "27"(字符串)// 如果要转整数int num = Integer.parseInt(input www.tiyu.gov.cn.yccgc.cn );  // "27" → 27
方法 输入 27 返回类型
nextLine() "27" String
nextInt() 27 int
nextDouble() 27.0 double

Q4: 常量池在堆上吗?

是的,现代 Java(7+)中,字符串常量池在堆上。

但常量池是堆中特殊管理的区域,与普通堆对象有区别:

对比维度 常量池对象 普通堆对象
位置 堆(特殊区域) 堆(普通区域)
创建方式 字面量、intern() new String()
去重 ✅ 自动去重 ❌ 不去重
生命周期 一般长期存在 无引用后 GC 回收

总结速查表

基本类型速查

类型 位数 范围 默认值
byte 8 -128 ~ 127 0
short 16 ±3.2万 0
int 32 ±21亿 0
long 64 极大 0L
float 32 单精度 0.0f
double 64 双精度 0.0
char 16 单字符 \u0000
boolean 1 true/false false

String 对比速查

操作 结果
String a = "hello";
String b = "hello";
a == b →  true
String c = new String("hello");
String d = new String("hello");
c == d →  false
a == c false(常量池 vs 堆)
a.equals(c) true(值相同)

记忆口诀

基础类型     引用类型    ↓            ↓
   栈          栈 + 堆
 直接值       引用+对象字面量       scanner输入    ↓            ↓
 常量池        堆新对象
 可复用        不复用String  → 引用同,值必同(不可变)
StringBuilder → 引用同,值随变(可变)


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70048949/viewspace-3109691/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2026-01-12

  • 博文量
    22
  • 访问量
    26017