2015-05-02 17 views
14

Tôi hiểu rằng trong Java trái với, ví dụ, C# generics là tính năng biên dịch-thời gian và được loại bỏ thông qua loại tẩy xoá. Vì vậy, làm thế nào để TypeToken của Gson thực sự hoạt động? Làm thế nào để nó có được kiểu chung của một đối tượng?Gson TypeToken hoạt động như thế nào?

Trả lời

18

It's a trick!

From §4.6 of the JLS (tôi nhấn mạnh):

Loại tẩy xoá là một ánh xạ từ các loại (có thể bao gồm các loại tham số và gõ biến) với các loại (nghĩa là không bao giờ loại tham số hoặc gõ biến). Chúng tôi viết | T | đối với xóa của loại T. Bản đồ tẩy xóa được xác định như sau:

Việc xóa một kiểu tham số (§4.5) G là | G |.

Tẩy xoá kiểu lồng nhau T.C là | T | .C.

Việc xóa một loại mảng T [] là | T | [].

Việc xóa biến kiểu (§4.4) là việc xóa bỏ giới hạn ngoài cùng bên trái của nó.

Việc xóa mọi loại khác là chính loại đó.

Do đó, nếu bạn khai báo một lớp có phân lớp ẩn danh, nó sẽ giữ kiểu tham số của nó; nó không bị xóa. Do đó, hãy xem xét đoạn mã sau:

import java.lang.reflect.ParameterizedType; 
import java.util.Arrays; 
import java.util.HashMap; 

public class Erasure<T> 
{ 
    public static void main(String...strings) { 
     Class<?> foo = new Erasure<HashMap<Integer, String>>() {}.getClass(); 
     ParameterizedType t = (ParameterizedType) foo.getGenericSuperclass(); 
     System.out.println(t.getOwnerType()); 
     System.out.println(t.getRawType()); 
     System.out.println(Arrays.toString(t.getActualTypeArguments())); 
    } 
} 

đầu ra này:

null 
class Erasure 
[java.util.HashMap<java.lang.Integer, java.lang.String>] 

Chú ý rằng bạn sẽ nhận được một ClassCastException nếu bạn không khai báo lớp nặc danh, vì bị tẩy xoá; siêu lớp sẽ không phải là loại được tham số hóa, nó sẽ là Object.

4

Loại xóa của Java áp dụng cho các đối tượng riêng lẻ, không phải các lớp hoặc trường hoặc phương thức. TypeToken sử dụng một lớp ẩn danh để đảm bảo nó giữ thông tin kiểu chung chung, thay vì chỉ tạo một đối tượng.

Các vấn đề liên quan