目录
-
Java 基本数据类型
(图片来源网络,侵删)- 什么是基本数据类型?
- 四大类八种
- 类型默认值
- 类型转换
-
Java String
String的特殊性- 不可变性
- 创建方式与内存分配
- 常用方法
-
基本数据类型与
String的转换- 基本类型 ->
String String-> 基本类型
- 基本类型 ->
Java 基本数据类型
什么是基本数据类型?
在 Java 中,数据类型分为两大类:基本数据类型 和 引用数据类型。
- 基本数据类型:Java 语言内置的、最简单的数据类型,它们不是对象,没有方法,变量中直接存储的是“值”本身,它们存储在栈内存 中,速度快,但空间有限。
- 引用数据类型:所有由
class,interface,array或enum创建的类型,它们的变量存储的是一个“引用”(内存地址),指向堆内存中的实际对象。
四大类八种
Java 定义了 8 种基本数据类型,可以分为 4 大类:

| 数据类型 | 大小 (字节) | 默认值 | 范围 | 说明 |
|---|---|---|---|---|
| 整数类型 | ||||
byte |
1 | 0 |
-128 ~ 127 | 字节,用于节省空间 |
short |
2 | 0 |
-32768 ~ 32767 | 短整型 |
int |
4 | 0 |
-2³¹ ~ 2³¹-1 | 最常用的整数类型 |
long |
8 | 0L |
-2⁶³ ~ 2⁶³-1 | 长整型,数字后加 L 或 l |
| 浮点类型 | ||||
float |
4 | 0f |
精确到小数点后 7 位 | 单精度浮点数,数字后加 f 或 F |
double |
8 | 0d |
精确到小数点后 15 位 | 最常用的浮点类型,数字后可加 d 或 D |
| 字符类型 | ||||
char |
2 | '\u0000' |
\u0000 ~ \uffff |
单个 16 位 Unicode 字符,用单引号 括起来 |
| 布尔类型 | ||||
boolean |
1 | false |
true / false |
只能取 true 或 false,通常用于逻辑判断 |
注意:
long类型的字面量必须后缀L,否则会被当作int处理,如果超出int范围会编译错误。long num = 10000000000L;float类型的字面量必须后缀f,否则会被当作double处理。float price = 19.99f;
类型默认值
当在类中定义成员变量(全局变量)但没有显式初始化时,Java 会为它们提供默认值。局部变量没有默认值,必须显式初始化才能使用。
| 数据类型 | 默认值 |
|---|---|
byte, short, int, long |
0 |
float, double |
0 |
char |
'\u0000' (空字符) |
boolean |
false |
| 所有引用类型 | null |
类型转换
基本数据类型之间可以转换,但要遵循规则:
-
自动类型转换 (隐式转换)
(图片来源网络,侵删)- 规则:从小类型到大类型转换,数据不会丢失。
- 顺序:
byte->short->int->long->float->double char->int也是自动的。- 示例:
int i = 100; long l = i; // int 自动转换为 long double d = i; // int 自动转换为 double
-
强制类型转换 (显式转换)
- 规则:从大类型到小类型转换,可能造成精度丢失或数据溢出。
- 语法:
(目标数据类型) 变量 - 示例:
double d = 9.8; int i = (int) d; // 强制转换,小数部分被舍弃,i 的值为 9 long l = 1000L; int j = (int) l; // long 强制转换为 int
Java String
String 是 Java 中最常用的引用数据类型,但它有一些非常特殊的性质。
String 的特殊性
String不是基本数据类型,它是一个final类,位于java.lang包中。- 它被广泛使用,以至于 Java 语言为其提供了一些“语法糖”,使得它的使用看起来像基本类型。
不可变性
这是 String 最核心、最重要的特性:String 对象一旦被创建,其内容(值)就不能被改变。
- 当你尝试修改一个
String对象时,JVM 实际上会创建一个新的String对象来存储修改后的内容,而原来的对象保持不变。 - 示例:
String s = "hello"; s = s + " world"; // 这行代码没有修改原来的 "hello" 对象 // 1. 首先在内存中创建一个新的字符串 "hello world" // 2. 然后让变量 s 指向这个新的对象 // 3. "hello" 对象如果不再被引用,就会被垃圾回收器回收
为什么设计成不可变?
- 线程安全:不可变对象天生就是线程安全的,因为它们不会被多个线程同时修改。
- 便于缓存和哈希不变,
String对象的hashCode()值在对象生命周期内也永远不会改变,这可以安全地作为HashMap等哈希结构中的键。 - 字符串常量池优化:JVM 为了优化性能,使用了一个特殊的内存区域——字符串常量池。
创建方式与内存分配
String 有两种主要的创建方式,它们的内存分配机制完全不同:
-
字面量赋值(推荐)
String s = "hello";- JVM 执行流程:
- 首先在字符串常量池 中查找是否存在
"hello"这个字符串。 - 如果存在,则直接将变量
s指向池中的"hello"。 - 如果不存在,则在池中创建一个新的
"hello"对象,然后将s指向它。
- 首先在字符串常量池 中查找是否存在
- 优点:可以复用池中的字符串对象,节省内存。
-
new关键字创建String s = new String("hello");- JVM 执行流程:
- 在堆内存 中创建一个新的
String对象,内容为"hello"。 - 检查字符串常量池中是否存在
"hello"。 - 如果不存在,则在池中也创建一个
"hello"对象。 - 将变量
s指向堆内存中创建的那个新对象。
- 在堆内存 中创建一个新的
- 缺点:无论如何都会在堆中创建新对象,如果池中没有,还会在池中再创建一个,效率较低,内存占用也较多。
示例对比:
String s1 = "hello";
String s2 = "hello"; // s1 和 s2 指向常量池中的同一个 "hello" 对象
System.out.println(s1 == s2); // 输出 true,比较的是地址(引用)
String s3 = new String("hello");
String s4 = new String("hello"); // s3 和 s4 分别指向堆中两个不同的 "hello" 对象
System.out.println(s3 == s4); // 输出 false
System.out.println(s1 == s3); // 输出 false,s1 在池中,s3 在堆中
常用方法
String 提供了非常丰富的方法来操作字符串:
length(): 返回字符串长度。charAt(int index): 返回指定索引处的字符。substring(int beginIndex, int endIndex): 截取子字符串。toUpperCase()/toLowerCase(): 转换为大写/小写。trim(): 去除字符串首尾的空格。split(String regex): 根据正则表达式分割字符串。equals(Object anObject): 比较字符串内容是否相等(区分大小写)。equalsIgnoreCase(String anotherString): 比较字符串内容是否相等(不区分大小写)。compareTo(String anotherString): 按字典顺序比较两个字符串。contains(CharSequence s): 判断是否包含指定序列。
基本数据类型与 String 的转换
在实际开发中,经常需要在基本数据类型和 String 之间进行转换。
基本类型 -> String
有三种常用方法:
-
使用 号(最简单)
int num = 123; String str1 = num + ""; // "" 是空字符串,与任何类型相加都会变成字符串拼接
-
使用
String.valueOf()(最推荐)int num = 123; String str2 = String.valueOf(num); // 代码更清晰,性能也较好 // 还有其他重载方法:valueOf(long, float, double, char, boolean, Object)
-
使用包装类的
toString()方法int num = 123; String str3 = Integer.toString(num); // long: Long.toString(), double: Double.toString() 等
String -> 基本类型
使用包装类的静态 parseXxx() 或 valueOf() 方法。
int:Integer.parseInt(String s)long:Long.parseLong(String s)double:Double.parseDouble(String s)float:Float.parseFloat(String s)boolean:Boolean.parseBoolean(String s)char:s.charAt(0)
示例与异常处理:
如果字符串格式不正确("abc" 无法转成数字),这些方法会抛出 NumberFormatException,在实际应用中最好使用 try-catch 结构。
String strNum = "100";
String strInvalid = "abc";
// 转换为 int
int num1 = Integer.parseInt(strNum); // 成功,num1 = 100
System.out.println(num1);
// 处理可能出现的异常
try {
int num2 = Integer.parseInt(strInvalid); // 会抛出 NumberFormatException
} catch (NumberFormatException e) {
System.out.println("无法将字符串 '" + strInvalid + "' 转换为整数!");
}
| 特性 | 基本数据类型 | String |
|---|---|---|
| 类型 | Java 内置,不是对象 | 引用数据类型(final 类) |
| 存储 | 栈内存 | 堆内存,字符串常量池 |
| 值 | 变量中直接存储值 | 变量中存储引用(地址) |
| 可变性 | 值可变 | 不可变 |
| 创建 | int a = 10; |
String s = "hello"; 或 new String("hello"); |
| 比较 | 比较值 | 比较引用地址,equals() 比较内容 |
| 转换 | 可通过强制/自动转换互转 | 可与基本类型通过包装类互相转换 |
理解这些基础概念对于编写高效、健壮的 Java 代码至关重要。
