.## 1. Kiến Thức Cơ Bản về Chuyển Đổi Giữa Số và Chuỗi trong Java
Khi phát triển bằng Java, bạn sẽ không thể tránh khỏi các tình huống như “dữ liệu trông giống số nhưng được xử lý như chuỗi” hoặc “giá trị nhận được dưới dạng chuỗi mà bạn muốn tính toán dưới dạng số”. Ví dụ, các đầu vào của form, nhập khẩu CSV, phản hồi API và đầu ra log thường đến dưới dạng chuỗi ngay cả khi chúng trông có vẻ là số.
Trong phần này, chúng ta sẽ sắp xếp lý do tại sao việc chuyển đổi là cần thiết và những điểm mà người mới thường gặp khó khăn.
- 1 2. Cách Chuyển Đổi Số Thành Chuỗi
- 2 3. Cách Chuyển Đổi Chuỗi Thành Số
- 3 4. Chuyển Đổi Sử Dụng BigDecimal và BigInteger (Tài Chính / Tính Toán Độ Chính Xác)
- 4 5. Các Lỗi Thường Gặp Khi Chuyển Đổi và Cách Xử Lý
- 5 6. Các Phương Pháp Chuyển Đổi Được Đề Xuất Theo Trường Hợp Sử Dụng
- 6 7. Sai lầm Thông thường và Anti‑Pattern
- 7 8. Tổng kết
- 8 9. Câu hỏi thường gặp (FAQ)
- 8.1 Q1. Cách tốt nhất duy nhất để chuyển đổi số thành chuỗi trong Java là gì?
- 8.2 Q2. Tôi nên sử dụng cái nào: parseInt hay valueOf?
- 8.3 Q3. Có cách nào để kiểm tra xem một chuỗi có phải là số học trước khi chuyển đổi không?
- 8.4 Q4. Tại sao NumberFormatException xảy ra trong quá trình chuyển đổi số học?
- 8.5 Q5. Tại sao tôi không nên sử dụng double cho các phép tính tiền bạc?
- 8.6 Q6. Tôi nên cẩn thận điều gì khi chuyển đổi giá trị đầu vào biểu mẫu thành số?
- 8.7 Q7. Điều gì nếu tôi muốn kiểm soát định dạng hiển thị sau khi chuyển đổi thành chuỗi?
1.1 Tại Sao Cần Chuyển Đổi
Các chương trình Java xử lý kiểu dữ liệu (type) một cách rõ ràng. Tuy nhiên, dữ liệu thực tế nhập vào và xuất ra thường trở thành “chuỗi”, chẳng hạn như:
- Nhập liệu của người dùng : Ngay cả khi bạn gõ “123” vào ô văn bản, chương trình nhận được cơ bản là một chuỗi
- Tệp (CSV / JSON / file cấu hình) : Khi đọc chúng, bạn thường nhận được các giá trị dưới dạng chuỗi
- HTTP/API : Nhiều giá trị được truyền dưới dạng chuỗi (hoặc kiểu JSON có thể không rõ ràng)
- Hiển thị và log : Thay vì xuất số nguyên như nó vốn có, thường chuyển đổi sang chuỗi và định dạng chúng
Vì vậy, trong công việc thực tế, hai hướng chuyển đổi thường xuất hiện thường xuyên:
- Number → String : hiển thị UI, log, thông báo, nối chuỗi, v.v.
- String → Number : tính toán, so sánh, kiểm tra phạm vi, tổng hợp, v.v.
Điều quan trọng ở đây là: ngay cả khi trông giống số, các kiểu khác nhau lại có ý nghĩa khác nhau.
"10"(chuỗi) và10(số) có thể trông giống nhau, nhưng chúng là các kiểu khác nhau trong mã- Chuỗi
"10" + "2"trở thành"102"(nối chuỗi) - Số
10 + 2trở thành12(cộng số)
Những lỗi như “tôi nghĩ mình đang cộng, nhưng lại thành nối chuỗi” dễ xảy ra nếu bạn không giữ sự phân biệt này trong đầu.
1.2 Java Rất Nghiêm Ngặt về Kiểu Dữ Liệu
Java là ngôn ngữ tĩnh kiểu, vì vậy các phép toán với kiểu không khớp thường dẫn đến lỗi biên dịch. Điều này tăng cường an toàn, nhưng khi chuyển đổi giữa các kiểu như chuỗi và số, bạn cần thực hiện chuyển đổi đúng cách.
Ví dụ, nếu bạn cố gắng dùng một chuỗi đầu vào trực tiếp như một số, bạn sẽ nhận được lỗi.
- Bạn muốn tính toán với chuỗi
"123"như mộtint→ Bạn phải chuyển đổi nó sanginttrước khi dùng
Thêm nữa, Java có hai loại kiểu số: kiểu nguyên thủy và lớp bao bọc, đây thường là nguồn gây nhầm lẫn.
- Kiểu nguyên thủy:
int,long,double, v.v. (nhẹ, là các số cơ bản) - Lớp bao bọc:
Integer,Long,Double, v.v. (số được xử lý như đối tượng)
Ví dụ, Integer.valueOf("123") trả về một Integer (đối tượng), trong khi Integer.parseInt("123") trả về một int (nguyên thủy).
Chúng ta sẽ đi sâu vào sự khác biệt này trong phần tiếp theo, nhưng người mới thường bối rối vì “cùng một chuyển đổi dường như trả về các kiểu khác nhau”.
1.3 Sự Khác Biệt Giữa Chuyển Đổi Tự Động và Chuyển Đổi Rõ Ràng
Khi nghe tới “chuyển đổi”, bạn có thể tưởng tượng Java tự động thực hiện. Thực tế, có một số hành vi trông giống như chuyển đổi tự động trong một số trường hợp.
Một ví dụ phổ biến là nối chuỗi.
- Nếu bạn viết
"Total: " + 10, số 10 dường như được tự động chuyển thành chuỗi
Tuy tiện lợi, nhưng cũng có thể gây ra kết quả không mong muốn.
"10" + 2→"102"(nối chuỗi, không phải cộng số)
Vì vậy, Java có những trường hợp giá trị được chuyển thành chuỗi một cách ngầm, nhưng String → Number hầu như không được chuyển đổi tự động.
Nói cách khác:
- Number → String : có thể xảy ra ngầm trong một số ngữ cảnh (như nối chuỗi)
- String → Number : luôn cần chuyển đổi rõ ràng (như parseInt)
Nhớ điều này sẽ giúp bạn tránh lỗi.
Ngoài ra, khi chuyển đổi chuỗi sang số, đầu vào không phải lúc nào cũng hợp lệ.
- Chuỗi rỗng
"" - Khoảng trắng
" 123 " - Dấu phẩy
"1,000" - Cố gắng chuyển đổi số thập phân
"12.34"sangint - Ký tự không phải số
"12a"
Trong những trường hợp như vậy, một ngoại lệ thời gian chạy (thường là NumberFormatException) sẽ xảy ra.
Trong các hệ thống thực tế, việc thiết kế với giả định “có thể có dữ liệu đầu vào không hợp lệ” là rất quan trọng.
2. Cách Chuyển Đổi Số Thành Chuỗi
Trong phần này, chúng ta sẽ giải thích các cách phổ biến nhất để chuyển số thành chuỗi trong Java, cùng với cách lựa chọn chúng.
Việc chuyển đổi này được sử dụng liên tục trong log, đầu ra giao diện người dùng và xây dựng thông điệp.
2.1 Sử Dụng String.valueOf() (Phổ Biến Nhất)
Để chuyển đổi số thành chuỗi, cách an toàn và được khuyến nghị nhất là String.valueOf().
int i = 100;
String s = String.valueOf(i);
Nó hỗ trợ không chỉ int mà còn long, double, float, boolean, và hầu hết các kiểu nguyên thủy.
double d = 12.34;
String s = String.valueOf(d);
Các tính năng chính của cách tiếp cận này:
- Cú pháp nhất quán, dễ nhớ
- Hoạt động với cả kiểu nguyên thủy và lớp wrapper
- Độ đọc cao
- Ý định rõ ràng (“đây là một chuyển đổi sang chuỗi” ngay lập tức)
Nó cũng chuyển đổi các đối tượng wrapper thành chuỗi một cách an toàn.
Integer num = null;
String s = String.valueOf(num); // "null"
Ngay cả khi bạn truyền null, nó cũng không ném NullPointerException, điều này đặc biệt hữu ích cho việc ghi log.
2.2 Sử Dụng Integer.toString() / Double.toString()
Mỗi lớp wrapper số cung cấp một phương thức tiện ích toString().
int i = 100;
String s = Integer.toString(i);
double d = 12.34;
String s = Double.toString(d);
Cách này hoạt động đúng, nhưng có những đặc điểm sau:
- Phương thức khác nhau tùy loại (Integer / Double / Long, v.v.)
- Việc nhớ tất cả chúng hơi phiền phức
- Ít đa năng hơn so với
String.valueOf()
Vì vậy trong các dự án thực tế, String.valueOf() thường được ưu tiên trừ khi bạn muốn nhấn mạnh một kiểu cụ thể.
2.3 Cảnh Báo Khi Gọi toString() Trên Đối Tượng
Bạn cũng có thể gọi trực tiếp toString() trên các đối tượng wrapper hoặc các đối tượng tự định nghĩa.
Integer i = 100;
String s = i.toString();
Cách này hoạt động, nhưng bạn phải cẩn thận nếu có khả năng null.
Integer i = null;
String s = i.toString(); // NullPointerException
Nếu đối tượng là null, sẽ gây ra lỗi thời gian chạy.
Để an toàn, String.valueOf() là lựa chọn tốt hơn trong các trường hợp như:
- Đầu ra log
- Tạo chuỗi debug
- Các luồng mã có thể xuất hiện null
2.4 Bạn Có Nên Dùng “+ “”” Để Chuyển Đổi Không?
Bạn có thể đã thấy mã như sau:
int i = 100;
String s = i + "";
Đúng, nó chuyển một số thành chuỗi. Tuy nhiên, đây không phải là cách được khuyến nghị.
Lý do:
- Ý định không rõ ràng ngay lập tức
- Không chắc chắn đây là phép nối chuỗi hay chuyển đổi
- Thường bị phản đối trong các buổi review code
- Dễ gây hiểu lầm khi thay đổi trong tương lai
Nó có thể xuất hiện trong các demo ngắn hoặc thử nghiệm nhanh, nhưng tốt nhất nên tránh trong mã có khả năng bảo trì.
2.5 Tóm Tắt: Cách Lựa Chọn Phương Pháp Chuyển Đổi Số → Chuỗi
Để tránh nhầm lẫn trong công việc thực tế, hãy nhớ:
- Lựa chọn mặc định: String.valueOf()
- Nếu muốn nhấn mạnh kiểu: Integer.toString() / Double.toString()
- Gọi toString() trên đối tượng cần chú ý null
- Tránh + “” về nguyên tắc
3. Cách Chuyển Đổi Chuỗi Thành Số
Từ đây, chúng ta sẽ giải thích chủ đề đặc biệt quan trọng trong các dự án thực tế: chuyển đổi chuỗi thành số.
Vì dữ liệu nhập từ người dùng và dữ liệu bên ngoài không được đảm bảo hợp lệ, việc hiểu các phương pháp chuyển đổi và các bẫy tiềm ẩn là cần thiết.
3.1 Sử Dụng Integer.parseInt() (Cơ Bản Nhất)
Một phương thức tiêu biểu để chuyển một chuỗi thành int là Integer.parseInt().
String s = "123";
int i = Integer.parseInt(s);
Phương thức này trả về kiểu nguyên thủy int, thuận tiện khi bạn muốn thực hiện tính toán hoặc so sánh ngay lập tức.
int total = Integer.parseInt("10") + Integer.parseInt("20");
// total is 30
Tuy nhiên, truyền các chuỗi như sau sẽ gây ra ngoại lệ thời gian chạy.
"abc"""(chuỗi rỗng)"12.3"(số thập phân)"1,000"(có dấu phẩy)int i = Integer.parseInt("abc"); // NumberFormatException
Ngoại lệ này không được phát hiện tại thời điểm biên dịch—nó xảy ra tại thời gian chạy, vì vậy bạn phải cẩn thận.
3.2 Sử dụng Integer.valueOf()
Integer.valueOf() là một cách đại diện khác để chuyển đổi chuỗi thành số.
String s = "123";
Integer i = Integer.valueOf(s);
Sự khác biệt lớn nhất so với parseInt() là kiểu trả về là Integer (lớp bao bọc).
parseInt()→intvalueOf()→Integer
Sự khác biệt này quan trọng trong các tình huống như:
- Lưu trữ giá trị trong bộ sưu tập (List / Map)
- Thiết kế xử lý null
- Khi bạn muốn xử lý giá trị như một đối tượng
Bên trong, valueOf() cũng ném NumberFormatException nếu chuyển đổi thất bại.
Vì vậy, nó không “ít lỗi hơn” so với parseInt().
3.3 Cách Chọn Giữa parseInt và valueOf
Nếu bạn không chắc chắn nên sử dụng cái nào, các tiêu chí này sẽ giúp:
- Nếu mục tiêu là tính toán hoặc so sánh → parseInt()
- Nếu bạn muốn xử lý nó như một đối tượng → valueOf()
Vì Java hiện đại có autoboxing, sự khác biệt thực tế nhỏ hơn, nhưng vẫn quan trọng để phát triển thói quen chọn dựa trên kiểu trả về.
3.4 Chuyển Đổi Sang Các Kiểu Số Khác Như double / long
Bạn thường cần chuyển đổi chuỗi thành các kiểu khác ngoài số nguyên.
long l = Long.parseLong("100000");
double d = Double.parseDouble("12.34");
Các quy tắc cơ bản là giống nhau:
Long.parseLong()→longDouble.parseDouble()→doubleFloat.parseFloat()→float
Tất cả chúng đều ném NumberFormatException nếu chuỗi không thể chuyển đổi.
Một sai lầm chính là cố gắng chuyển đổi chuỗi thập phân thành kiểu số nguyên:
int i = Integer.parseInt("12.34"); // exception
Trong trường hợp đó, bạn cần một thiết kế xử lý giá trị như double từ đầu.
3.5 Cẩn Thận Với Khoảng Trống Đầu/Cuối
Đầu vào từ người dùng thường chứa khoảng trắng không chủ ý.
String s = " 123 ";
int i = Integer.parseInt(s); // exception
Trong những trường hợp như vậy, thường sử dụng trim() trước khi chuyển đổi.
int i = Integer.parseInt(s.trim());
Tuy nhiên, ngay cả sau trim(), ngoại lệ vẫn xảy ra nếu còn ký tự không phải số.
3.6 Tóm Tắt: Các Điểm Chính Cho Chuyển Đổi Chuỗi → Số
Để chuyển đổi chuỗi thành số một cách an toàn, hãy ghi nhớ những điểm này:
- Luôn không tin tưởng đầu vào bên ngoài
- Thiết kế giả định rằng ngoại lệ có thể xảy ra
- Quyết định kiểu số rõ ràng (int / long / double)
- Tiền xử lý khi cần (trim, v.v.)
4. Chuyển Đổi Sử Dụng BigDecimal và BigInteger (Tài Chính / Tính Toán Độ Chính Xác)
Các kiểu int và double được giới thiệu cho đến nay rất tiện lợi, nhưng bạn phải cẩn thận khi độ chính xác tính toán là quan trọng.
Đặc biệt đối với tiền bạc, số lượng và tỷ lệ, BigDecimal và BigInteger được sử dụng để tránh làm tròn và vấn đề độ chính xác.
4.1 Tại Sao double Không Đủ
Vì double là kiểu dấu phẩy động, nó được lưu trữ bên trong như một xấp xỉ trong nhị phân.
Kết quả là, bạn có thể thấy hành vi như thế này:
double d = 0.1 + 0.2;
System.out.println(d); // 0.30000000000000004
Đây không phải là lỗi—đó là thiết kế.
Nó có thể trông nhỏ, nhưng có thể gây chết người trong các trường hợp như:
- Tính toán tiền bạc
- Xử lý hóa đơn và thanh toán
- Tính toán tích lũy lãi suất hoặc tỷ lệ
Trong những trường hợp như vậy, bạn cần một kiểu không giới thiệu lỗi dấu phẩy động.
4.2 Chuyển Đổi Chuỗi → Số Sử Dụng BigDecimal
Với BigDecimal, quy tắc là: tạo nó từ chuỗi.
BigDecimal bd = new BigDecimal("12.34");
Một mẫu bạn nên tránh là:
BigDecimal bd = new BigDecimal(12.34); // not recommended
Vì double gốc đã chứa lỗi xấp xỉ, chuyển đổi sang BigDecimal sẽ mang lỗi đó theo.
Nhớ rằng: luôn tạo BigDecimal từ String.
.### 4.3 Chuyển Đổi Number → String (BigDecimal)
Để chuyển BigDecimal thành chuỗi, thường dùng toString().
BigDecimal bd = new BigDecimal("12.3400");
String s = bd.toString(); // "12.3400"
Nếu muốn định dạng hiển thị, bạn có thể dùng DecimalFormat, nhưng thực hành tốt nhất là tách việc xử lý nội bộ ra khỏi định dạng hiển thị.
4.4 Khi Nào Nên Dùng BigInteger
BigInteger được dùng để xử lý các số nguyên rất lớn.
BigInteger bi = new BigInteger("12345678901234567890");
Các trường hợp sử dụng điển hình:
- Các số có số chữ số cực kỳ lớn
- Đại diện số cho ID hoặc giá trị hash
- Các phép tính nguyên vượt quá phạm vi của
long
Nó ít phổ biến trong các ứng dụng kinh doanh thông thường, nhưng rất hiệu quả khi bạn phải xử lý các số nguyên có giới hạn không xác định hoặc không giới hạn.
4.5 Tóm Tắt: Cách Nhìn Nhận BigDecimal / BigInteger
- Tiền tệ / các phép tính yêu cầu độ chính xác cao → BigDecimal
- Các số nguyên khổng lồ → BigInteger
- BigDecimal nên được tạo từ String
- Giữ việc định dạng tách riêng khỏi các phép tính
5. Các Lỗi Thường Gặp Khi Chuyển Đổi và Cách Xử Lý
Khi chuyển đổi chuỗi thành số, bạn phải luôn giả định có thể xảy ra lỗi.
Trong phần này, chúng ta sẽ tổng hợp các ngoại lệ phổ biến và các cách xử lý an toàn.
5.1 NumberFormatException Là Gì?
NumberFormatException là một ngoại lệ thời gian chạy được ném ra khi chuỗi không thể được diễn giải thành một số.
int i = Integer.parseInt("abc"); // NumberFormatException
Ngoại lệ này không được phát hiện ở thời điểm biên dịch—nó chỉ xuất hiện khi code chạy.
Do đó, nếu dữ liệu đầu vào đến từ bên ngoài (form, file, API, v.v.), bạn luôn phải tính đến khả năng này.
Các nguyên nhân phổ biến bao gồm:
- Chứa ký tự không phải số
- Chuỗi rỗng hoặc null
- Cố gắng chuyển đổi một số thập phân sang kiểu số nguyên
- Chứa dấu phẩy hoặc ký hiệu (ví dụ: “1,000”)

5.2 Xử Lý Cơ Bản Bằng try-catch
Cách tiếp cận cơ bản nhất là sử dụng try-catch để bắt ngoại lệ.
try {
int i = Integer.parseInt(input);
} catch (NumberFormatException e) {
// Handling when conversion fails
}
Các điểm chính:
- Xử lý lỗi một cách đáng tin cậy
- Làm cho hành vi khi thất bại trở nên rõ ràng
- Thường được sử dụng nhất trong các dự án thực tế
Kết hợp với việc ghi log và thông báo lỗi, cách này cho phép xử lý an toàn.
5.3 Cách Tiền Kiểm Tra Để Tránh Ngoại Lệ
Ngoài việc bắt ngoại lệ, bạn cũng có thể kiểm tra trước xem chuỗi có phải là số hay không.
boolean isNumber = input.matches("\\d+");
Bằng một biểu thức chính quy, bạn có thể kiểm tra xem chuỗi chỉ chứa các chữ số. Tuy nhiên, có một số lưu ý quan trọng:
- Khó hỗ trợ số thập phân và số âm
- Có thể trở nên phức tạp
- Không cung cấp sự đảm bảo hoàn toàn
Vì vậy, trong thực tế, việc coi try-catch là lưới an toàn cuối cùng là hợp lý.
5.4 Cẩn Thận Với null và Chuỗi Rỗng
Trước khi thực hiện chuyển đổi sang số, cần kiểm tra xem chuỗi có phải là null hoặc rỗng hay không.
if (input == null || input.isEmpty()) {
// Error handling
}
Bỏ qua kiểm tra này có thể dẫn đến ngoại lệ hoặc hành vi không mong muốn.
Chuỗi rỗng đặc biệt phổ biến trong các trường nhập form và file cấu hình.
5.5 Tóm Tắt: Cách Nhìn Nhận Xử Lý Lỗi
- Xem dữ liệu đầu vào bên ngoài là có thể không hợp lệ
- Dùng try-catch để bắt ngoại lệ một cách đáng tin cậy
- Dùng tiền kiểm tra như một biện pháp bổ sung
- Loại bỏ sớm các chuỗi null và rỗng
6. Các Phương Pháp Chuyển Đổi Được Đề Xuất Theo Trường Hợp Sử Dụng
Cho đến nay, chúng ta đã đề cập đến các cách chính để chuyển đổi giữa số và chuỗi trong Java.
Trong phần này, chúng ta sẽ sắp xếp tư duy dựa trên trường hợp sử dụng để bạn không ngần ngại khi thực hiện trong dự án thực tế.
6.1 Hiển Thị UI và Ghi Log
Đối với hiển thị UI và log, an toàn và dễ đọc là ưu tiên hàng đầu.
Đề xuất:
- Number → String:
String.valueOf() - Ngay cả khi đối tượng có thể là một kiểu khác, vẫn dùng
String.valueOf()log.info("count=" + String.valueOf(count));
Ngay cả khi null có thể xuất hiện, nó vẫn ngăn ngừa các ngoại lệ.
6.2 Tính toán và So sánh
Đối với tính toán và so sánh, quy tắc cơ bản là chuyển đổi sang kiểu số càng sớm càng tốt.
- Chuỗi → Số:
parseInt()/parseLong()/parseDouble() - Sau khi chuyển đổi, thực hiện toàn bộ xử lý bằng các kiểu số
int price = Integer.parseInt(inputPrice); int total = price * quantity;
Tiếp tục xử lý dưới dạng chuỗi có thể gây ra các lỗi tinh vi.
6.3 Đầu vào Form và Xử lý Dữ liệu Ngoại vi
Xem xét đầu vào người dùng và dữ liệu ngoại vi với giả định rằng các giá trị không hợp lệ sẽ đến.
- Kiểm tra
null/ chuỗi rỗng - Xử lý ngoại lệ bằng try‑catch
- Trả về thông báo lỗi khi cần thiết
try { int age = Integer.parseInt(input); } catch (NumberFormatException e) { // Input error handling }
Tránh viết “chỉ có đường đi hạnh phúc”—hãy nghĩ về các đường đi lỗi trước.
6.4 Xử lý Tiền tệ và Các trường hợp Yêu cầu Độ chính xác Cao
Đối với tiền tệ, tỷ lệ và các trường hợp khác mà lỗi dấu phẩy động không chấp nhận được, hãy sử dụng BigDecimal.
- Chuỗi →
BigDecimal:new BigDecimal(String) - Tách riêng việc định dạng hiển thị khỏi các phép tính
BigDecimal amount = new BigDecimal(inputAmount);
Điều quan trọng là không đi qua double.
6.5 Lưu trữ trong Collection hoặc Xử lý dưới dạng Đối tượng
Khi lưu giá trị vào List hoặc Map, hoặc khi thiết kế của bạn xử lý null, các lớp wrapper là phù hợp.
Integer.valueOf()Long.valueOf()List<Integer> list = new ArrayList<>(); list.add(Integer.valueOf("10"));
6.6 Tóm tắt Các Trường hợp Sử dụng
Tóm tắt theo trường hợp sử dụng:
- Hiển thị / log →
String.valueOf() - Tính toán →
parseXxx() - Tiền tệ / độ chính xác →
BigDecimal - Đầu vào ngoại vi → thiết kế cho ngoại lệ
- Collection →
valueOf()
7. Sai lầm Thông thường và Anti‑Pattern
Việc chuyển đổi giữa số và chuỗi là cơ bản, nhưng cả người mới bắt đầu và các nhà phát triển có kinh nghiệm đều có thể mắc lỗi.
Phần này tóm tắt các anti‑pattern bạn nên tránh trong các dự án thực tế.
7.1 Cố gắng Tính toán Khi Vẫn Giữ Chuỗi
Đoạn mã này có vẻ hợp lý nhưng thực tế rủi ro:
String a = "10";
String b = "20";
String result = a + b; // "1020"
Đây không phải là phép tính—đó là nối chuỗi.
Đối với các phép tính số, hãy chuyển đổi sang kiểu số trước:
int result = Integer.parseInt(a) + Integer.parseInt(b); // 30
7.2 Lạm dụng Chuyển đổi “+ “””
String s = value + "";
Nó hoạt động, nhưng ý định không rõ ràng và khả năng bảo trì thấp, vì vậy không được khuyến khích.
- Thường bị chỉ ra trong các buổi review code
- Gây nhầm lẫn cho người đọc sau này
- Không rõ là chuyển đổi hay nối chuỗi
Sử dụng String.valueOf() một cách rõ ràng sẽ an toàn hơn.
7.3 Truyền double Trực tiếp vào BigDecimal
BigDecimal bd = new BigDecimal(0.1); // not recommended
Điều này nguy hiểm vì nó sử dụng một double đã chứa sai số xấp xỉ.
Cách tiếp cận đúng là:
BigDecimal bd = new BigDecimal("0.1");
Đối với tiền tệ và các trường hợp yêu cầu độ chính xác cao, luôn tạo BigDecimal từ chuỗi.
7.4 Viết Code Giả Định Ngoại lệ Không Bao Giờ Xảy ra
int i = Integer.parseInt(input);
Trong các dự án thực tế, giả định rằng đầu vào luôn hợp lệ hiếm khi đúng.
Khi xử lý đầu vào ngoại vi, luôn bao gồm xử lý ngoại lệ:
try {
int i = Integer.parseInt(input);
} catch (NumberFormatException e) {
// Error handling
}
7.5 Sử dụng Giá trị Mà Không Nhận Thức Được Sự Khác Biệt Kiểu Dữ liệu
Cũng thường gặp việc sử dụng các kiểu mà không suy nghĩ về sự khác nhau như int vs Integer, hoặc double vs BigDecimal.
- Mục tiêu của bạn là tính toán?
- Mục tiêu của bạn là hiển thị?
- Độ chính xác có quan trọng không?
Lựa chọn kiểu dựa trên mục đích là cách nhanh nhất để ngăn ngừa lỗi.
8. Tổng kết
Trong Java, việc chuyển đổi giữa số và chuỗi là việc làm hàng ngày, nhưng đồng thời cũng là quá trình mà những sai lầm nhỏ có thể dẫn đến các vấn đề nghiêm trọng.
Những điểm chính rút ra từ bài viết này:
- Đối với Number → String,
String.valueOf()là mặc định - Đối với String → Number, chọn giữa
parseXxx()vàvalueOf()dựa trên kiểu trả về - Xử lý đầu vào bên ngoài giả định rằng ngoại lệ có thể xảy ra
- Sử dụng
BigDecimalcho tiền bạc và các phép tính yêu cầu độ chính xác - Tránh các mẫu mơ hồ như
+ ""
Thay vì ghi nhớ các phương thức, điều quan trọng hơn là chọn dựa trên trường hợp sử dụng và kiểu.
Với tư duy này, bạn sẽ ít bị kẹt hơn trong xử lý cơ bản của Java.
9. Câu hỏi thường gặp (FAQ)
Ở đây chúng tôi tóm tắt các điểm vấp ngã phổ biến cho độc giả tìm kiếm “java number string conversion” dưới dạng Q&A.
Phần này nhằm lấp đầy các khoảng trống có thể còn lại sau khi đọc văn bản chính.
Q1. Cách tốt nhất duy nhất để chuyển đổi số thành chuỗi trong Java là gì?
Nói chung, phương pháp được khuyến nghị nhất là String.valueOf().
Lý do:
- Nhất quán và dễ hiểu
- Hoạt động với cả kiểu nguyên thủy và lớp bao bọc
- Không ném ngoại lệ khi truyền null
String s = String.valueOf(100);
Trong các dự án thực tế, sử dụng cái này làm mặc định giúp bạn tránh sai lầm.
Q2. Tôi nên sử dụng cái nào: parseInt hay valueOf?
Chọn dựa trên kiểu trả về.
Integer.parseInt()→int(nguyên thủy)Integer.valueOf()→Integer(lớp bao bọc)
Nếu mục tiêu của bạn là tính toán, sử dụng parseInt().
Nếu bạn muốn lưu trữ nó trong bộ sưu tập hoặc xử lý nó như một đối tượng, valueOf() phù hợp hơn.
Q3. Có cách nào để kiểm tra xem một chuỗi có phải là số học trước khi chuyển đổi không?
Một cách tiếp cận đơn giản là sử dụng biểu thức chính quy.
boolean isNumber = input.matches("\\d+");
Tuy nhiên, phương pháp này có hạn chế:
- Số thập phân và số âm khó hỗ trợ
- Nó không thể đảm bảo an toàn hoàn toàn
Vì vậy, trong thực tế, tốt nhất là giả định rằng try-catch vẫn cần thiết như biện pháp an toàn cuối cùng.
Q4. Tại sao NumberFormatException xảy ra trong quá trình chuyển đổi số học?
NumberFormatException xảy ra khi một chuỗi không thể được diễn giải như một số.
Nguyên nhân phổ biến:
- Chứa ký tự không phải số
- Chuỗi rỗng hoặc null
- Cố gắng chuyển đổi số thập phân thành kiểu số nguyên
- Chứa dấu phẩy hoặc ký hiệu
Khi xử lý đầu vào bên ngoài, luôn thiết kế dưới giả định rằng ngoại lệ có thể xảy ra.
Q5. Tại sao tôi không nên sử dụng double cho các phép tính tiền bạc?
Vì double được lưu trữ như một xấp xỉ trong nhị phân, lỗi dấu chấm động có thể xảy ra.
double d = 0.1 + 0.2; // 0.30000000000000004
Đối với tiền bạc, tỷ lệ, và các trường hợp yêu cầu độ chính xác khác, lựa chọn đúng là sử dụng BigDecimal được tạo từ chuỗi.
BigDecimal bd = new BigDecimal("0.1");
Q6. Tôi nên cẩn thận điều gì khi chuyển đổi giá trị đầu vào biểu mẫu thành số?
Luôn ghi nhớ những điểm này:
- Kiểm tra null / chuỗi rỗng
- Bắt ngoại lệ với try-catch
- Xác định hành vi rõ ràng cho các trường hợp lỗi
Xử lý đầu vào người dùng như “có thể không hợp lệ” theo mặc định để ngăn chặn lỗi.
Q7. Điều gì nếu tôi muốn kiểm soát định dạng hiển thị sau khi chuyển đổi thành chuỗi?
Giữ cho việc chuyển đổi số và định dạng hiển thị riêng biệt.
- Chuyển đổi:
String.valueOf()hoặcBigDecimal - Định dạng: sử dụng
DecimalFormat, v.v.
Tách biệt xử lý nội bộ khỏi trình bày cải thiện khả năng bảo trì.

