2017-10-19 17 views
8

Tôi có lớp sau đây:Java - Sử dụng lớp tham số trong phương pháp tham số

public class Publisher<T> { 

    private static final Class[] SUPPORTED_CLASSES = new Class[]{T1.class, T2.class}; 

    public Publisher() { 
     if(Arrays.asList(SUPPORTED_CLASSES).contains(T)) { // error: expression expected! 
      System.out.println("Class not supported!"); 
     } 
    } 
} 

Làm thế nào tôi có thể kiểm tra nếu tham số lớp phù hợp với việc thực hiện?
Trong ví dụ trên, tôi không thể sử dụng tham số lớp T làm tham số.

+0

Kiểm tra chủ đề này https://stackoverflow.com/questions/3403909/get-generic-type-of-class-at-runtime –

+3

Tại sao bạn muốn điều này, nếu tôi có thể yêu cầu? –

+0

@MCEmperor Tôi muốn kiểm tra xem lớp học có được hỗ trợ và đăng nhập thông báo cảnh báo nếu cần thiết – FazoM

Trả lời

13

Tại sao điều này không làm việc

Bạn đang cố gắng truy cập vào một kiểu generic trong thời gian chạy, mà không làm việc trong trường hợp này, vì type erasure.

Làm thế nào để sửa chữa

Cách đơn giản nhất để khắc phục điều này là để có một Class<T> trong các nhà xây dựng, mà sẽ cung cấp cho bạn các loại tại thời gian chạy, sau đó bạn có thể kiểm tra nếu danh sách chứa các giá trị mà bạn đã được trao .

Ví dụ mã

public Publisher(Class<T> clazz) { 
    if(!SUPPORTED_CLASSES.contains(clazz)) { 
     System.out.println("Class not supported!"); 
    } 
} 

Vấn đề có thể

Mã của bạn hiện không hỗ trợ phân nhóm, mà có thể gây ra các vấn đề, trừ khi bạn là ok với điều này (bạn có thể làm việc trên danh sách, nhưng không nhất thiết ArrayLists) Mặc dù vậy, điều này sẽ làm hỏng số LSP.

+0

Tôi muốn nói rằng một lý do cơ bản hơn tại sao mã OP không hoạt động là các đối số kiểu như' T' chỉ định * loại * , không phải đồ vật.Đặc biệt, chúng không giống như và không đại diện cho các đối tượng thuộc kiểu 'java.lang.Class', chẳng hạn như các đối tượng mà mảng của OP chứa. Các loại không phải là đối số bình thường hợp lệ. –

+0

LSP chỉ là một vấn đề nếu lớp của OP được coi là biến đổi trong T. Nếu nó trái ngược hoặc bất biến, đây là một cách hoàn toàn hợp pháp (nếu kỳ lạ và không phải là OOP) để làm việc. – Kevin

4

Bạn sẽ cần phải vượt qua lớp thành các nhà xây dựng:

public Publisher(Class<T> clazz) { 
    if(!SUPPORTED_CLASSES.contains(clazz)) { 
     System.out.println("Class not supported!"); 
    } 
} 

T không có sẵn tại thời gian chạy: chính xác cùng mã sẽ được thực hiện cho new Publisher<T1>()new Publisher<T3>().

6

Mặc dù một số câu trả lời khác là khá tốt, tôi xin đề xuất cách giải quyết khác:

Bạn có thể tạo một giao diện trống MyInterface, và có tất cả các lớp trong danh sách của bạn thực hiện giao diện này. Sau đó, bạn có thể thay đổi tuyên bố lớp học của mình thành:

public class Publisher<T extends S, MyInterface> 

sẽ đạt được mục đích của bạn.

+1

Đây là giải pháp tốt hơn nếu bạn có quyền kiểm soát tất cả các lớp bạn cần hỗ trợ, nhưng nếu bạn cần hỗ trợ các lớp bạn chưa viết, bạn có thể cần thực hiện theo cách khác. – jrtapsell

+1

@jrtapsell trong trường hợp xấu nhất, nếu bạn không phải hỗ trợ quá nhiều lớp, sử dụng cầu nối cho mỗi lớp bạn cần (một trình bao bọc đơn giản trên thực tế) triển khai giao diện – AxelH

+0

Khi giải pháp của bạn chỉ hoạt động với các lớp thực hiện một giao diện, bạn không cần danh sách các lớp tương thích nữa và chỉ có thể khai báo lớp đó là 'public class Publisher ' – Philipp

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