Type erasure trong java và manifest trong scala
Scala
50
Java
77
White

huydx viết ngày 18/08/2015

Type erasure là gì?

Chắc bạn nào làm java cũng biết đến khái niệm "type erasure" trong lập trình generic. Thông tin chi tiết có ghi trên homepage.

Về cơ chế: khi lập trình generic tức là bạn phải truyền "type" vào một method hoặc class nào đó, ở java sử dụng ký hiệu <T>, ở scala sử dụng kí hiệu [T]. Vì lý do lịch sử, khi truyền một type T vào đâu đó java compiler sẽ "xoá" toàn bộ type parameter được truyền vào và thay toàn bộ type T bằng type Object. Bạn có thể hiểu quá trình type erasure khá dễ dàng thông qua ví dụ sau:

Ví dụ 1: Class

  • before
public class Node<T> {

    private T data;
    private Node<T> next;

    public Node(T data, Node<T> next) }
        this.data = data;
        this.next = next;
    }

    public T getData() { return data; }
    // ...
}
  • after
public class Node {

    private Object data;
    private Node next;

    public Node(Object data, Node next) {
        this.data = data;
        this.next = next;
    }

    public Object getData() { return data; }
    // ...
}

Ví dụ 2: Method

  • before
public static <T> int count(T[] anArray, T elem) {
    int cnt = 0;
    for (T e : anArray)
        if (e.equals(elem))
            ++cnt;
        return cnt;
}
  • after
public static int count(Object[] anArray, Object elem) {
    int cnt = 0;
    for (Object e : anArray)
        if (e.equals(elem))
            ++cnt;
        return cnt;
}

Type Erasure gây ra vấn đề gì

Nói một cách đơn giản, nó gây ra vấn đề khi bạn muốn "thao tác" với type bạn truyền vào.
Trên trang chủ của oracle chúng ta có một list những hạn chế với generic :
https://docs.oracle.com/javase/tutorial/java/generics/restrictions.html

Mình ví dụ một hạn chế đơn giản nhất là: không thể khởi tạo mới một type generic được truyền vào

public static <E> void append(List<E> list) {
    E elem = new E();  // compile-time error
    list.add(elem);
}

Vụ ở trên là một vụ rất hay gặp khi lập trình với java. Để work around nó thì chúng ta có thể truyền Class Object vào

public static <E> void append(List<E> list, Class<E> cls) throws Exception {
    E elem = cls.newInstance();   // OK
    list.add(elem);
}

Type Erasure và scala

Khi lập trình generic với scala, bạn sẽ gặp những vấn đề hoàn toàn tương tự, vì generic trong scala cũng bị erase tương tự như java.
Thử dùng lại ví dụ tương tự ở trên của java:

def append[T](list:List[T]) = {
    val c = new T() //compile error
    list.append(c)
}

Để work around thì chúng ta cũng làm một thao tác y hệt là truyền class vào, cơ mà trong scala thì thay vào truyền Class Object thì chúng ta truyền một thứ gọi là ClassManifest

def append[T](list:List[T], m: ClassManifest[T]) = {
    val c =  m.erasure.newInstance() //OK
    list.append(c)
}

Tuy nhiên lần nào cũng truyền ClassManifest vào thì khá thừa thãi đặc biệt là khi T chỉ đơn thuần là các primitive type như Int hay là Float.., martin xem ra không thích việc này và ông đã implement sẵn cho chúng ta ClassManifest của hầu hết các object thông dụng. Do đó chúng ta chỉ cần thêm từ khoá implicit

def append[T](list:List[T], implicit m: ClassManifest[T]) = {
    val c =  m.erasure.newInstance() //OK
    list.append(c)
}

append(List(1,2,3)) //OK
Bình luận


White
{{ comment.user.name }}
Bỏ hay Hay
{{comment.like_count}}
Male avatar
{{ comment_error }}
Hủy
   

Hiển thị thử

Chỉnh sửa

White

huydx

116 bài viết.
945 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}
Cùng một tác giả
White
148 14
Introduction (Link) là một cuộc thi ở Nhật, và cũng chỉ có riêng ở Nhật. Đây là một cuộc thi khá đặc trưng bởi sự thú vị của cách thi của nó, những...
huydx viết gần 2 năm trước
148 14
White
118 15
Happy programmer là gì nhỉ, chắc ai đọc xong title của bài post này cũng không hiểu ý mình định nói đến là gì :D. Đầu tiên với cá nhân mình thì hap...
huydx viết hơn 3 năm trước
118 15
White
95 10
(Ảnh) Mở đầu Chắc nhiều bạn đã nghe đến khái niệm oauth. Về cơ bản thì oauth là một phương thức chứng thực, mà nhờ đó một web service hay một ap...
huydx viết 3 năm trước
95 10
Bài viết liên quan
White
0 0
Trong bài viết này, một số hình ảnh hoặc nọi dung có thể bị thiếu do quá trình chế bản. Vui lòng xem nội dung ở blog gốc sau: (Link) (Link), chúng...
programmerit viết gần 3 năm trước
0 0
Male avatar
9 5
Facade Design Patern Facade Patern thuộc vào họ mô hình cấu trúc (structural patern). Facade patern phát biểu rằng : "just provide a unified an...
DuongVanTien viết gần 2 năm trước
9 5
{{like_count}}

kipalog

{{ comment_count }}

bình luận

{{liked ? "Đã kipalog" : "Kipalog"}}


White
{{userFollowed ? 'Following' : 'Follow'}}
116 bài viết.
945 người follow

 Đầu mục bài viết

Vẫn còn nữa! x

Kipalog vẫn còn rất nhiều bài viết hay và chủ đề thú vị chờ bạn khám phá!