0

[Java Backend Zero to Hello] BÀI 1.12: WRAPPER CLASS & AUTOBOXING

Java Backend Zero to Hello

📚 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:

  1. Tạo class Student với: id, name, age, gpa
  2. Implement Comparable<Student> để sắp xếp theo GPA giảm dần
  3. Tạo class StudentManager với:
    • addStudent(Student s)
    • removeStudent(String id)
    • findByName(String name)
    • findByGpaRange(double min, double max)
    • sortByGpa() / sortByName()
    • getTopNStudents(int n)
    • getAverageGpa()
  4. Menu console với Scanner
  5. 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

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí