Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Java

Cách chuyển đổi ArrayList<String> sang ArrayList<Object> và ngược lại trong Java

Do Java Generics là invariant: ArrayList<String> KHÔNG phải subtype của ArrayList<Object>. Ép kiểu trực tiếp báo lỗi compile.

Cách 1: Wildcard ? (Type erasure trick)

Dùng ArrayList<?> làm trung gian (raw type an toàn hơn).

ArrayList<Object> objList = new ArrayList<>();
objList.add("apples"); objList.add("mangoes");

// Object -> String (Unsafe tại runtime nếu objList chứa non-String!)
ArrayList<String> strList = (ArrayList<String>)(ArrayList<?>) objList;

// Hoặc an toàn hơn: copy
ArrayList<String> safeStrList = new ArrayList<>(objList); // Warning unchecked

Cách 2: Copy qua Constructor (Khuyên dùng - An toàn)

// String -> Object (Luôn an toàn: String IS-A Object)
ArrayList<String> strList = new ArrayList<>();
strList.add("apples");
ArrayList<Object> objList = new ArrayList<>(strList); // OK, implicit upcast

// Object -> String (CẦN KIỂM TRA runtime)
ArrayList<Object> objList2 = new ArrayList<>();
objList2.add("apples");
objList2.add(123); // Integer!

// Cách an toàn: filter & copy
ArrayList<String> strList2 = objList2.stream()
    .filter(String.class::isInstance)
    .map(String.class::cast)
    .collect(Collectors.toCollection(ArrayList::new));

Tóm tắt quy tắc

Chuyển đổiAn toàn?Cách làm
ArrayList<String> → ArrayList<Object>✅ An toànnew ArrayList<>(stringList)
ArrayList<Object> → ArrayList<String>❌ UnsafePhải check runtime hoặc dùng wildcard cast (rủi ro ClassCastException)

Tại sao Generic invariant?

// Nếu cho phép: List objList = stringList;
objList.add(new Integer(123)); // Hợp lệ cho List
// Nhưng stringList giờ chứa Integer! -> Lỗi khi get String

Khuyên dùng: Thiết kế API dùng List<T> thay vì ArrayList<T>. Dùng List<? extends T> (producer) hoặc List<? super T> (consumer) cho flexibility (PECS principle).