1. Java 中数字与字符串相互转换的基础知识
在 Java 开发中,你不可避免会遇到类似“看起来像数字但被当作字符串处理”的情况,或是“以字符串形式接收的值需要计算成数字”。例如,表单输入、CSV 导入、API 响应以及日志输出常常以字符串形式出现,即使它们看起来是数值。
本节我们将梳理为何需要转换,以及初学者常碰到的难点。
1.1 为什么会需要转换
Java 程序需要显式地处理数据类型(type)。然而,实际业务中的数据输入输出往往是 字符串,比如:
- 用户输入:即使在文本框里键入 “123”,程序收到的基本上也是一个字符串
- 文件(CSV / JSON / 配置文件):读取时通常得到的是字符串形式的值
- HTTP / API:很多值都是以字符串传递的(或 JSON 类型不明确)
- 显示和日志:为了美化输出,常常会把数字转换为字符串并进行格式化
因此,在实际工作中经常会出现两种方向的转换:
- 数字 → 字符串:用于 UI 显示、日志、消息、拼接等
- 字符串 → 数字:用于计算、比较、范围检查、聚合等
这里关键是:即使看起来是数值,不同的类型在代码中意义不同。
"10"(字符串)和10(数字)表面相同,但在代码中是不同的类型- 字符串
"10" + "2"会得到"102"(字符串拼接) - 数字
10 + 2会得到12(数值相加)
如果不牢记这一点,就很容易出现 “我以为在做加法,结果却变成了字符串拼接” 的错误。
1.2 Java 对类型的严格要求
Java 是静态类型语言,类型不匹配的操作通常会导致 编译时错误。这提升了安全性,但在字符串与数字之间切换时,需要进行适当的转换。
例如,直接把字符串输入当作数字使用,就会报错。
- 想用字符串
"123"进行int计算 → 必须先把它转换为int再使用
此外,Java 有两类数值类型:基本类型(primitive types) 和 包装类(wrapper classes),这常常是混淆的来源。
- 基本类型:
int、long、double等(轻量、直接的数值) - 包装类:
Integer、Long、Double等(以对象形式存在的数值)
例如,Integer.valueOf("123") 返回 Integer(对象),而 Integer.parseInt("123") 返回 int(基本类型)。
我们将在下一节详细讨论这一区别,但初学者常因 “相同的转换却返回不同的类型” 而卡住。
1.3 自动转换与显式转换的区别
提到 “转换”,有时会误以为 Java 会自动完成。实际上,只有在特定情况下会出现类似自动转换的行为。
一个常见例子是 字符串拼接。
- 写
"Total: " + 10时,10 看起来会被自动转换为字符串
虽然方便,但也可能导致意外结果。
"10" + 2→"102"(字符串拼接,而非数值相加)
因此,Java 在某些场景下会隐式地把值转为字符串,但 字符串 → 数字 基本上 不会自动转换。换句话说:
- 数字 → 字符串:在某些上下文(如拼接)中可以隐式发生
- 字符串 → 数字:始终需要显式转换(如
parseInt)
记住这一点可以帮助你避免错误。
另外,字符串转数字时,输入并不总是有效的。例如:
- 空字符串
"" - 含空格的字符串
" 123 " - 带千位分隔符的
"1,000" - 将小数
"12.34"转为int - 含非数字字符的
"12a"
在这种情况下,会抛出运行时异常(通常是 NumberFormatException)。
在实际系统中,设计时必须假设“可能会收到无效输入”,这点至关重要。
2. 将数字转换为字符串
在本节中,我们将说明在 Java 中将数字转换为字符串的最常见方法,并介绍如何在它们之间进行选择。
这种转换在日志、UI 输出以及消息构建中经常使用。
2.1 使用 String.valueOf()(最常用)
将数字转换为字符串时,最安全且最推荐的做法是 String.valueOf()。
int i = 100;
String s = String.valueOf(i);
它不仅支持 int,还支持 long、double、float、boolean,以及几乎所有原始类型。
double d = 12.34;
String s = String.valueOf(d);
此方法的关键特性:
- 语法一致,易于记忆
- 同时适用于原始类型和包装类
- 可读性高
- 意图明确(“一眼就能看出是字符串转换”)
它还能安全地将包装对象转换为字符串。
Integer num = null;
String s = String.valueOf(num); // "null"
即使传入 null,也不会抛出 NullPointerException,这在日志记录时尤为有用。
2.2 使用 Integer.toString() / Double.toString()
每个数值包装类都提供了 toString() 实用方法。
int i = 100;
String s = Integer.toString(i);
double d = 12.34;
String s = Double.toString(d);
此方法能够正常工作,但具有以下特点:
- 不同类型使用不同的方法(Integer / Double / Long 等)
- 需要记住所有这些方法有点繁琐
- 通用性不如
String.valueOf()
因此在实际项目中,除非需要明确强调特定类型,否则通常更倾向于使用 String.valueOf()。
2.3 调用对象的 toString() 时的注意事项
也可以直接对包装对象或自定义对象调用 toString()。
Integer i = 100;
String s = i.toString();
此方式可行,但如果可能为 null时必须小心。
Integer i = null;
String s = i.toString(); // NullPointerException
如果对象为 null,会导致运行时错误。
为保证安全,String.valueOf() 更适用于以下场景:
- 日志输出
- 调试字符串生成
- 可能出现 null 的代码路径
2.4 是否应该使用 “+ “”” 进行转换?
你可能见过如下代码:
int i = 100;
String s = i + "";
是的,它可以把数字转换为字符串。但这并不是推荐的做法。
原因如下:
- 意图不够直观
- 难以判断是拼接还是转换
- 在代码评审中常被批评
- 在后续修改时更容易产生误解
它可能出现在简短的演示或快速测试中,但在可维护的代码中最好避免使用。
2.5 小结:如何选择数字 → 字符串的转换方式
为避免实际工作中的混淆,请记住以下要点:
- 默认选择:String.valueOf()
- 如果想强调类型:Integer.toString() / Double.toString()
- 对对象调用 toString() 时需注意 null
- 原则上避免使用 + “”
3. 将字符串转换为数字
接下来,我们将说明在实际项目中尤为重要的主题:将字符串转换为数字。
由于用户输入和外部数据不一定有效,了解转换方法及其陷阱至关重要。
3.1 使用 Integer.parseInt()(最基础)
将字符串转换为 int 的代表性方法是 Integer.parseInt()。
String s = "123";
int i = Integer.parseInt(s);
该方法返回原始类型 int,在需要立即进行计算或比较时非常方便。
int total = Integer.parseInt("10") + Integer.parseInt("20");
// total is 30
但是,传入如下字符串会导致运行时异常。
"abc"""(空字符串)"12.3"(小数)"1,000"(带逗号)int i = Integer.parseInt("abc"); // NumberFormatException
此异常不会在编译时检测到——它在运行时发生,因此你必须小心。
3.2 使用 Integer.valueOf()
Integer.valueOf() 是将字符串转换为数字的另一种常用方式。
String s = "123";
Integer i = Integer.valueOf(s);
与 parseInt() 最大的区别在于返回类型是 Integer(包装类)。
parseInt()→intvalueOf()→Integer
这种差异在以下场景中很重要:
- 在集合中存储值(List / Map)
- 处理 null 的设计
- 当你想把该值视为对象时
在内部,如果转换失败,valueOf() 同样会抛出 NumberFormatException。因此它并不像 parseInt() 那样“更不易出错”。
3.3 如何在 parseInt 与 valueOf 之间做选择
如果你不确定该使用哪一个,以下标准可以帮助你:
- 如果目标是计算或比较 → parseInt()
- 如果想把它当作对象处理 → valueOf()
由于现代 Java 支持自动装箱,实际差异变小,但仍然重要的是养成根据返回类型进行选择的习惯。
3.4 转换为其他数值类型,如 double / long
你经常需要将字符串转换为整数以外的类型。
long l = Long.parseLong("100000");
double d = Double.parseDouble("12.34");
基本规则相同:
Long.parseLong()→longDouble.parseDouble()→doubleFloat.parseFloat()→float
如果字符串无法转换,它们都会抛出 NumberFormatException。
一个关键的陷阱是尝试将小数字符串转换为整数类型:
int i = Integer.parseInt("12.34"); // exception
在这种情况下,你需要一种从一开始就把该值视为 double 的设计。
3.5 警惕前导/尾随空格
用户输入常常会不经意地包含空格。
String s = " 123 ";
int i = Integer.parseInt(s); // exception
在这种情况下,通常会在转换前使用 trim()。
int i = Integer.parseInt(s.trim());
然而,即使使用了 trim(),如果仍然存在非数字字符,仍会抛出异常。
3.6 小结:字符串 → 数字 转换的关键要点
要安全地将字符串转换为数字,请牢记以下要点:
- 始终不信任外部输入
- 设计时假设可能会抛出异常
- 明确决定数值类型(int / long / double)
- 必要时进行预处理(trim 等)
4. 使用 BigDecimal 和 BigInteger 进行转换(金融 / 精度计算)
前面介绍的 int 和 double 类型使用方便,但在计算精度至关重要的情况下必须小心。尤其是涉及金钱、数量和比率时,使用 BigDecimal 和 BigInteger 可以避免四舍五入和精度问题。
4.1 为什么 double 不够
因为 double 是浮点类型,它在内部以二进制近似的形式存储。因此,你可能会看到如下行为:
double d = 0.1 + 0.2;
System.out.println(d); // 0.30000000000000004
这不是 bug——而是设计如此。虽然看起来微不足道,但在以下情况下可能致命:
- 金钱计算
- 账单和结算处理
- 利率或比例的累计计算
在这些情况下,你需要一种不会引入浮点误差的类型。
4.2 使用 BigDecimal 进行字符串 → 数字转换
使用 BigDecimal 时,规则是:从字符串创建。
BigDecimal bd = new BigDecimal("12.34");
应避免的模式是:
BigDecimal bd = new BigDecimal(12.34); // not recommended
因为原始的 double 已经包含近似误差,转换为 BigDecimal 会把该误差带进去。
记住:始终从字符串创建 BigDecimal。
4.3 Number → String Conversion (BigDecimal)
要将 BigDecimal 转换为字符串,通常使用 toString()。
BigDecimal bd = new BigDecimal("12.3400");
String s = bd.toString(); // "12.3400"
如果需要显示格式化,可以使用 DecimalFormat,但最佳实践是 将内部处理与显示格式分离。
4.4 When to Use BigInteger
BigInteger 用于处理 非常大的整数。
BigInteger bi = new BigInteger("12345678901234567890");
典型使用场景:
- 位数极多的数字
- ID 或哈希值的数值表示
- 超出
long范围的整数运算
在典型的业务应用中较少使用,但在必须处理未知或无限制的整数时非常有效。
4.5 Summary: How to Think About BigDecimal / BigInteger
- 金额 / 精度关键的计算 → BigDecimal
- 超大整数 → BigInteger
- BigDecimal 应 从 String 创建
- 将格式化与计算分离
5. Common Errors During Conversion and How to Handle Them
在将字符串转换为数字时,必须假设 错误随时可能发生。
本节将整理常见异常及安全的处理方式。
5.1 What Is NumberFormatException?
NumberFormatException 是在 字符串无法被解释为数字 时抛出的运行时异常。
int i = Integer.parseInt("abc"); // NumberFormatException
该异常不会在编译时检测到——只有在代码运行时才会出现。
因此,如果输入来自外部(表单、文件、API 等),必须始终考虑到它。
常见原因包括:
- 包含非数字字符
- 空字符串或 null
- 将小数转换为整数类型
- 包含逗号或符号(例如
"1,000")

5.2 Basic Handling with try-catch
最基本的做法是使用 try-catch 捕获异常。
try {
int i = Integer.parseInt(input);
} catch (NumberFormatException e) {
// Handling when conversion fails
}
关键点:
- 可靠地处理错误路径
- 明确地表现失败行为
- 在真实项目中最常使用
结合日志和错误信息,可实现安全的处理。
5.3 A Pre-check Approach to Avoid Exceptions
除了异常处理之外,还可以在此之前 验证是否为数字。
boolean isNumber = input.matches("\\d+");
使用正则表达式可以检查字符串是否仅包含数字。但有以下重要注意事项:
- 难以支持小数和负数
- 可能变得复杂
- 并不能提供完整的保证
因此,在实际中,合理的做法是将 try-catch 视为最终的安全网。
5.4 Be Careful with null and Empty Strings
在进行数字转换之前,务必检查是否为 null 或空字符串。
if (input == null || input.isEmpty()) {
// Error handling
}
跳过此检查可能导致异常或意外行为。
空字符串在表单输入和配置文件中尤为常见。
5.5 Summary: How to Think About Error Handling
- 将外部输入视为可能无效
- 使用 try-catch 可靠捕获异常
- 使用预检查作为补充验证
- 及早排除 null 和空字符串
6. Recommended Conversion Methods by Use Case
到目前为止,我们已经介绍了 Java 中数字与字符串相互转换的主要方式。
本节将整理 基于使用场景的思考方式,帮助你在实际开发中不再犹豫。
6.1 UI Display and Log Output
对于 UI 显示和日志,安全性和可读性是首要考虑。
推荐:
- Number → String:
String.valueOf() - 即使可能涉及对象,也使用
String.valueOf()log.info("count=" + String.valueOf(count));
即使可能出现 null,也能防止异常。
6.2 计算与比较
对于计算和比较,基本规则是 尽早转换为数值类型。
- String → Number:
parseInt()/parseLong()/parseDouble() - 转换后,使用数值类型完成后续处理
int price = Integer.parseInt(inputPrice); int total = price * quantity;
继续以字符串方式处理可能导致细微的错误。
6.3 表单输入与外部数据处理
在假设 会收到无效值 的前提下处理用户输入和外部数据。
- null / 空字符串检查
- 通过 try-catch 进行异常处理
- 根据需要返回错误信息
try { int age = Integer.parseInt(input); } catch (NumberFormatException e) { // Input error handling }
避免只写 “happy path”——首先考虑错误路径。
6.4 金额与精度关键的处理
对于金额、费率以及其他 不能接受浮点误差 的情况,使用 BigDecimal。
- String → BigDecimal:
new BigDecimal(String) - 将显示格式化与计算分离
BigDecimal amount = new BigDecimal(inputAmount);
关键是不要经过 double。
6.5 在集合中存储或作为对象处理
在 List 或 Map 中存储值,或在设计中需要处理 null 时,使用包装类是合适的。
Integer.valueOf()Long.valueOf()List<Integer> list = new ArrayList<>(); list.add(Integer.valueOf("10"));
6.6 用例总结
按用例总结:
- 显示 / 日志 →
String.valueOf() - 计算 →
parseXxx() - 金额 / 精度 →
BigDecimal - 外部输入 → 为异常设计
- 集合 →
valueOf()
7. 常见错误与反模式
数字与字符串之间的转换是基础,但 初学者和有经验的开发者都可能犯错。
本节总结了在实际项目中应避免的反模式。
7.1 试图在保持字符串的情况下进行计算
这段代码看起来合理,但风险很大:
String a = "10";
String b = "20";
String result = a + b; // "1020"
这不是计算,而是 字符串拼接。
对于数值计算,首先要转换为数值类型:
int result = Integer.parseInt(a) + Integer.parseInt(b); // 30
7.2 过度使用 “+ “”” 转换
String s = value + "";
它可以工作,但 意图不明确且可维护性低,因此不推荐使用。
- 在代码审查时可能会被指出
- 以后会让阅读者困惑
- 模糊不清是转换还是拼接
显式使用 String.valueOf() 更安全。
7.3 直接将 double 传入 BigDecimal
BigDecimal bd = new BigDecimal(0.1); // not recommended
这很危险,因为 它使用了已经包含近似误差的 double。
正确的做法是:
BigDecimal bd = new BigDecimal("0.1");
对于金额和精度关键的情况,始终从字符串创建。
7.4 编写代码时假设异常不会发生
int i = Integer.parseInt(input);
在实际项目中,输入始终有效的假设很少成立。
处理外部输入时,始终要加入异常处理:
try {
int i = Integer.parseInt(input);
} catch (NumberFormatException e) {
// Error handling
}
7.5 在不了解类型差异的情况下使用值
常见的情况是使用类型时没有考虑 int 与 Integer、double 与 BigDecimal 等差异。
- 你的目标是计算吗?
- 你的目标是显示吗?
- 精度是否关键?
根据目的选择类型是防止 bug 的最快方法。
8. 总结
在 Java 中,数字与字符串的相互转换是日常操作,但也是一个 小错误可能导致重大问题 的过程。
本文的关键要点:
- 对于 Number → String,
String.valueOf()是默认选项 - 对于 String → Number,根据返回类型在
parseXxx()与valueOf()之间选择 - 处理外部输入时假设可能会抛出异常
- 对于金钱及对精度要求高的计算使用
BigDecimal - 避免使用模糊的写法,如
+ ""
与其记住各种方法,不如根据使用场景和类型来选择。
有了这种思路,你在 Java 基础处理上卡住的情况会大大减少。
9. 常见问题解答 (FAQ)
这里我们以问答形式总结了读者在搜索 “java number string conversion” 时常遇到的难点。
本节旨在填补阅读正文后可能仍存在的空白。
Q1. 在 Java 中将数字转换为字符串的最佳方式是什么?
一般来说,最推荐的做法是 String.valueOf()。
原因如下:
- 行为一致且易于理解
- 兼容基本类型和包装类
- 当传入
null时不会抛出异常String s = String.valueOf(100);
在实际项目中,将其设为默认做法可以帮助你避免错误。
Q2. 应该使用 parseInt 还是 valueOf?
根据 返回类型 来决定。
Integer.parseInt()→int(基本类型)Integer.valueOf()→Integer(包装类)
如果你的目标是进行数值运算,使用 parseInt();
如果要把结果存入集合或作为对象使用,valueOf() 更合适。
Q3. 在转换之前,有没有办法检查字符串是否为数字?
一种简单的做法是使用正则表达式。
boolean isNumber = input.matches("\\d+");
但该方法也有局限性:
- 对小数和负数的支持较为困难
- 不能保证完全安全
因此,在实际使用中,仍然需要把 try‑catch 作为最终的安全保障。
Q4. 为什么在数值转换时会出现 NumberFormatException?
NumberFormatException 出现在 字符串无法被解释为数字 时。
常见原因包括:
- 含有非数字字符
- 空字符串或
null - 试图把小数转换为整数类型
- 包含逗号或其他符号
处理外部输入时,务必假设可能会抛出异常并做好相应设计。
Q5. 为什么不建议使用 double 来进行金钱计算?
因为 double 在二进制中是近似存储的,会产生浮点误差。
double d = 0.1 + 0.2; // 0.30000000000000004
对于金钱、利率以及其他对精度要求高的场景,正确的做法是 使用由字符串创建的 BigDecimal。
BigDecimal bd = new BigDecimal("0.1");
Q6. 将表单输入值转换为数字时需要注意什么?
始终牢记以下要点:
- 检查
null/ 空字符串 - 使用 try‑catch 捕获异常
- 为错误情况定义明确的处理行为
默认把用户输入视为“可能无效”,以防止潜在 bug。
Q7. 转换为字符串后,如何控制显示格式?
保持数值转换与显示格式的分离。
- 转换:
String.valueOf()或BigDecimal - 格式化:使用
DecimalFormat等工具
将内部处理与表现层分离,有助于提升代码的可维护性。

