Type erasure trong java và manifest trong scala
Scala
50
Java
164
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

118 bài viết.
1235 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}
Cùng một tác giả
White
219 20
Một ngày đẹp trời, bạn quyết định viết một dịch vụ web dự định sẽ làm thay đổi cả thế giới. Dịch vụ của bạn sẽ kết nối tất cả các thiết bị di động ...
huydx viết 2 năm trước
219 20
White
192 15
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 4 năm trước
192 15
White
151 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 5 năm trước
151 15
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 5 năm trước
0 0
White
10 0
Kí tự Regex cơ bản Về cơ bản thì các sử lý matching của scala.util.matching.Regex sẽ được "phó thác" (delegate) cho java Regex. Bạn có thể tạo một ...
huydx viết 5 năm trước
10 0
{{like_count}}

kipalog

{{ comment_count }}

bình luận

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


White
{{userFollowed ? 'Following' : 'Follow'}}
118 bài viết.
1235 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á!