[Java Backend Zero to Hello] BÀI 1.12: WRAPPER CLASS & AUTOBOXING
📚 Bài viết thuộc series Java Backend Zero to Hello 📌 Phần: Phase 1: Java Core Cơ Bản | Bài 14/86
BÀI 1.12: WRAPPER CLASS & AUTOBOXING
Mục tiêu
- Hiểu Wrapper class và vai trò
- Nắm cơ chế Autoboxing và Unboxing
- Sử dụng các method tiện ích của Wrapper
- Hiểu về Cache và hiệu năng
1. WRAPPER CLASS LÀ GÌ?
Wrapper class là class bao bọc kiểu dữ liệu nguyên thủy thành object, cho phép sử dụng các kiểu primitive trong các ngữ cảnh yêu cầu object (Collection, Generic, ...).
Bảng Wrapper
| Primitive | Wrapper | Kích thước |
|---|---|---|
byte |
Byte |
1 byte |
short |
Short |
2 bytes |
int |
Integer |
4 bytes |
long |
Long |
8 bytes |
float |
Float |
4 bytes |
double |
Double |
8 bytes |
char |
Character |
2 bytes |
boolean |
Boolean |
1 bit |
2. TẠO WRAPPER OBJECT
2.1 Constructor (deprecated từ Java 9)
Integer i1 = new Integer(100); // ❌ Không khuyến khích
Integer i2 = Integer.valueOf(100); // ✅ Khuyến khích
Integer i3 = 100; // ✅ Autoboxing
2.2 valueOf - Khuyến khích
Integer i = Integer.valueOf(100);
Double d = Double.valueOf(3.14);
Boolean b = Boolean.valueOf(true);
2.3 parseXxx - Chuyển String thành primitive
int i = Integer.parseInt("123");
double d = Double.parseDouble("3.14");
boolean b = Boolean.parseBoolean("true");
2.4 valueOf(String) - Chuyển String thành Wrapper
Integer i = Integer.valueOf("123");
Double d = Double.valueOf("3.14");
3. AUTOBOXING VÀ UNBOXING
3.1 Autoboxing - Tự động chuyển primitive → Wrapper
Integer i = 100; // Autoboxing: Integer.valueOf(100)
List<Integer> list = new ArrayList<>();
list.add(50); // Autoboxing: list.add(Integer.valueOf(50))
3.2 Unboxing - Tự động chuyển Wrapper → primitive
Integer i = 100;
int j = i; // Unboxing: i.intValue()
int sum = list.get(0); // Unboxing
3.3 Ví dụ tổng hợp
public static int sum(List<Integer> numbers) {
int total = 0; // primitive
for (Integer num : numbers) { // Wrapper
total += num; // Unboxing tự động
}
return total;
}
4. CACHE CỦA WRAPPER
Java cache các giá trị thường dùng để tối ưu hiệu năng.
4.1 Integer Cache (-128 đến 127)
Integer a = 100;
Integer b = 100;
System.out.println(a == b); // true (cùng object trong cache)
Integer c = 200;
Integer d = 200;
System.out.println(c == d); // false (ngoài cache, khác object)
4.2 So sánh Wrapper
Integer a = 100;
Integer b = 100;
// ❌ So sánh tham chiếu - không đáng tin
System.out.println(a == b); // true (trong cache)
// ✅ So sánh giá trị - luôn dùng
System.out.println(a.equals(b)); // true
System.out.println(a.intValue() == b.intValue()); // true
💡 Best practice: Luôn dùng
.equals()để so sánh Wrapper, không dùng==.
5. CÁC METHOD TIỆN ÍCH
5.1 Integer
int max = Integer.MAX_VALUE; // 2147483647
int min = Integer.MIN_VALUE; // -2147483648
int size = Integer.SIZE; // 32 (bits)
int bytes = Integer.BYTES; // 4
// Chuyển đổi
String s = Integer.toString(123); // "123"
String s2 = Integer.toBinaryString(10); // "1010"
String s3 = Integer.toHexString(255); // "ff"
// Parse
int i = Integer.parseInt("123");
int i2 = Integer.parseInt("ff", 16); // 255 (hệ 16)
// So sánh
int cmp = Integer.compare(5, 10); // -1
5.2 Double
double d = Double.parseDouble("3.14");
boolean isInfinite = Double.isInfinite(d);
boolean isNaN = Double.isNaN(d);
double d2 = Double.parseDouble("Infinity"); // Infinity
5.3 Character
char c = 'A';
boolean isDigit = Character.isDigit(c); // false
boolean isLetter = Character.isLetter(c); // true
boolean isUpper = Character.isUpperCase(c); // true
boolean isLower = Character.isLowerCase(c); // false
boolean isWhitespace = Character.isWhitespace(' '); // true
char upper = Character.toUpperCase('a'); // 'A'
char lower = Character.toLowerCase('Z'); // 'z'
5.4 Boolean
boolean b1 = Boolean.parseBoolean("true"); // true
boolean b2 = Boolean.parseBoolean("TRUE"); // true (case-insensitive)
boolean b3 = Boolean.parseBoolean("yes"); // false
boolean b4 = Boolean.parseBoolean("1"); // false
6. NULL TRONG WRAPPER
Wrapper có thể là null, primitive thì không.
Integer i = null;
int j = i; // ❌ NullPointerException khi unboxing
// Phải kiểm tra null
if (i != null) {
int j = i;
}
Ví dụ thực tế
public int getValue(Map<String, Integer> map, String key) {
Integer value = map.get(key);
if (value == null) {
return 0; // Giá trị mặc định
}
return value; // Unboxing an toàn
}
7. HIỆU NĂNG
7.1 So sánh
// Chậm - autoboxing/unboxing nhiều
Long sum = 0L;
for (long i = 0; i < Integer.MAX_VALUE; i++) {
sum += i; // Mỗi lần cộng đều boxing/unboxing
}
// Nhanh - dùng primitive
long sum = 0L;
for (long i = 0; i < Integer.MAX_VALUE; i++) {
sum += i;
}
7.2 Khi nào dùng Wrapper
- Lưu trong Collection (
List<Integer>,Map<String, Integer>) - Generic (
T extends Number) - Có thể null
- Cần dùng method tiện ích
7.3 Khi nào dùng Primitive
- Tính toán số học
- Vòng lặp
- So sánh
- Mặc định trong code thường
8. STREAM VỚI WRAPPER
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.stream()
.mapToInt(Integer::intValue) // Chuyển sang IntStream
.sum();
OptionalDouble avg = numbers.stream()
.mapToInt(Integer::intValue)
.average();
9. BÀI TẬP THỰC HÀNH
Bài 1: Chuyển đổi mảng
public static int[] toPrimitive(Integer[] arr) {
int[] result = new int[arr.length];
for (int i = 0; i < arr.length; i++) {
result[i] = arr[i]; // Unboxing
}
return result;
}
public static Integer[] toWrapper(int[] arr) {
Integer[] result = new Integer[arr.length];
for (int i = 0; i < arr.length; i++) {
result[i] = arr[i]; // Autoboxing
}
return result;
}
Bài 2: Validate số điện thoại
public static boolean isValidPhone(String phone) {
if (phone == null || phone.isEmpty()) return false;
for (char c : phone.toCharArray()) {
if (!Character.isDigit(c)) return false;
}
return phone.length() >= 10;
}
Bài 3: Tính tổng an toàn với null
public static int safeSum(List<Integer> numbers) {
int sum = 0;
for (Integer num : numbers) {
if (num != null) {
sum += num;
}
}
return sum;
}
Bài 4: Chuyển đổi hệ cơ số
public static String toBinary(int n) {
return Integer.toBinaryString(n);
}
public static int fromBinary(String binary) {
return Integer.parseInt(binary, 2);
}
10. TÓM TẮT
| Khái niệm | Điểm chính |
|---|---|
| Wrapper class | Object bao bọc primitive |
| Autoboxing | Primitive → Wrapper tự động |
| Unboxing | Wrapper → Primitive tự động |
| valueOf | Tạo Wrapper (có cache) |
| parseXxx | String → primitive |
| Cache | Integer cache -128 đến 127 |
| So sánh | Dùng .equals(), không dùng == |
| Null | Wrapper có thể null, primitive không |
11. BÀI TẬP CUỐI PHASE 1
Quản lý sinh viên (CRUD console app)
Yêu cầu:
- Tạo class
Studentvới: id, name, age, gpa - Implement
Comparable<Student>để sắp xếp theo GPA giảm dần - Tạo class
StudentManagervới:addStudent(Student s)removeStudent(String id)findByName(String name)findByGpaRange(double min, double max)sortByGpa()/sortByName()getTopNStudents(int n)getAverageGpa()
- Menu console với Scanner
- Lưu trữ trong
ArrayList<Student>
Code mẫu:
public class Student implements Comparable<Student> {
private String id;
private String name;
private int age;
private double gpa;
public Student(String id, String name, int age, double gpa) {
this.id = id;
this.name = name;
this.age = age;
this.gpa = gpa;
}
// Getters, setters, toString, equals, hashCode
@Override
public int compareTo(Student other) {
return Double.compare(other.gpa, this.gpa);
}
}
Hoàn thành Phase 1! Tiếp tục với Phase 2: Java Core nâng cao
🧭 Điều Hướng Series
⬅️ Bài trước: BÀI 1.11: COLLECTIONS FRAMEWORK (PHẦN 2)
📋 Lộ trình tổng quan: Xem Toàn Bộ Series
➡️ Bài tiếp theo: PHASE 2: JAVA CORE NÂNG CAO - Tổng Quan & Mục Tiêu
All rights reserved