2014-07-01 17 views
8

Tôi gặp vấn đề với các đối số kiểu rõ ràng của phương thức chung. Tôi biết tôi có thể làm điều này:Đối số loại phương thức chung Java

Foo.<Bar>function(); 

giả sử có một chức năng

void <T> function() {...} 

trong lớp Foo. Vấn đề chính xác là:

  • Tôi muốn tải về một số nội dung (Android với Ion)

  • Những nội dung tương đồng (Điều, BlogArticle, ...), tất cả thực hiện một giao diện ContentItem

  • Tại thời điểm này tải trông như thế này:

tin tức ví dụ

private void downloadNews() { 
    Ion.with(this) 
    .load(URL_NEWS) 
    .as(new TypeToken<List<Article>>(){}) 
    .setCallback(new FutureCallback<List<Article>>() { 
     @Override 
     public void onCompleted(Exception e, List<Article> result) { 
      // do something with result 
     } 
    }); 
} 

Nếu tôi muốn tải xuống các bài viết trên blog, tôi phải thay đổi url và Chỉ lớp bài viết (cho BlogArticle).

tôi đã cố gắng để thực hiện một chức năng chung chung như thế này:

private <T extends ContentItem> void download(String url) { 
    Ion.with(this) 
    .load(url) 
    .as(new TypeToken<List<T>>(){}) 
    .setCallback(new FutureCallback<List<T>>() { 
     @Override 
     public void onCompleted(Exception e, List<T> result) { 
      // do something with result 
     } 
    }); 
} 

và gọi đó là chức năng

this.<Article>download(url); 

Đó là ok, biên dịch tốt. Sau khi chạy tôi nhận được

java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap không thể được đúc để com.my.packagename.model.ContentItem

Vấn đề là nó doesn không sử dụng lớp rõ ràng để ánh xạ Json vào thư mục.

Bạn có thể đề xuất cho tôi giải pháp chung không?

+0

Những dòng để bạn có được những lỗi trên? – shmosel

+2

Xem http://stackoverflow.com/questions/24505314/parsing-json-to-list-of-items-with-generic-field-with-gson – axtavt

+0

Nó trỏ đến dòng đầu tiên của lớp, vì vậy không có gì thú vị –

Trả lời

0

Năm sau, nhưng tôi nghĩ nó có thể hữu ích cho ai đó. Tôi đã kết thúc với một giải pháp đơn giản hơn. Nó chỉ là một đơn giản, phiên bản cắt ngắn nhưng bạn có thể lấy ý tưởng:

public static <T> void asList(Context context, String url, Class<T[]> clazz, final FutureCallback<List<T>> callback) { 
    Ion.with(context) 
     .load(url) 
     .as(clazz) 
     .setCallback(new FutureCallback<T[]>() { 
      @Override 
       public void onCompleted(Exception e, T[] result) { 
        callback.onCompleted(e, Arrays.asList(result)); 
       } 
     }); 
} 

Và sử dụng như:

asList(context, url, YourObject[].class, new FutureCallback<List<YourObject>>() {...}); 
-1

gì về việc sử dụng

private <T implements ContentItem> void download(String url) { 
.... 

Kể từ khi các lớp học thực hiện giao diện ContentItem, họ không mở rộng giao diện

+0

Nó không hợp lệ. Bạn phải viết mở rộng ngay cả khi đó là một giao diện. –

1

Tôi nghĩ rằng không có cách nào để thực hiện những gì bạn muốn trong một thời trang generic sử dụng phương pháp TypeToken. Trong thực tế, lưu ý rằng đối với các loại thẻ để làm việc, bạn cần phải tạo một lớp bên trong vô danh. Bằng cách này, bạn có thể tạo một classfile mới, có supertype được đổi thành List<Article>.Nói cách khác, nó giống như nếu bạn đã khai báo như sau:

class ArticleToken extends TypeToken<List<Article>> { ... } 

Nếu bạn đã viết tờ khai trên chính mình, bạn sẽ nhận thấy rằng ArticleToken.class classfile theo dõi những siêu kiểu generic trong các thuộc tính như vậy gọi Signature (xem JVMS). Do đó, thủ thuật này cho phép bạn truy cập siêu kiểu chung sau này, bằng cách gọi Class.getGenericSupertype. Nói cách khác, nó là một thành ngữ của các tướng lĩnh thống nhất giả.

Nếu bạn bật mã của bạn vào một phương pháp chung và thay thế Điều với kiểu biến T, những gì xảy ra là kiểu thẻ bạn tạo là như thế này:

class GenericToken extends TypeToken<List<T>> { ... } 

Vì vậy, các thông tin về T được lưu trữ như là trong classfile, và nếu reflectiopn yêu cầu supertype chung của kiểu token, bạn chỉ cần lấy TypeToken<List<T>> trở lại chứ không phải TypeToken<List<Article>> như bạn mong đợi mà sau đó gây ra vấn đề bạn đang thấy. Những gì bạn cần để thực hiện công việc này là các generics được chỉnh sửa đúng, trong đó binding T to Article tại trang gọi phương thức sẽ ảnh hưởng đến hành vi thời gian chạy của new TypeToken<List<T>> - nhưng thật đáng buồn, không phải trường hợp Java sử dụng Generics đã xóa.

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