2016-06-15 13 views
9

Trong mã này,@SafeVarargs về phương pháp giao diện

package com.example; 

interface CollectorIF<T> { 
    // @SafeVarargs   // Error: @SafeVarargs annotation cannot be applied to non-final instance method addAll 
    void addAll(T... values); 
} 

class Collector<T> implements CollectorIF<T> { 

    @SafeVarargs 
    public final void addAll(T... values) { 
    } 
} 

class Component<T> { 

    public void compute(T value) { 
     Collector<T> col1 = new Collector<>(); 
     col1.addAll(value); // No warning 

     CollectorIF<T> col2 = new Collector<>(); 
     col2.addAll(value); // Type safety: A generic array of T is created for a varargs parameter 
    } 
} 

cảnh báo Type safety: A generic array of T is created for a varargs parameter không xảy ra khi sử dụng một tài liệu tham khảo Collector<T>, do @SafeVarargs chú thích.

Tuy nhiên, cảnh báo hiện xảy ra khi truy cập phương thức qua giao diện CollectorIF<T>. Trên các phương thức giao diện, @SafeVarargs không hợp lệ (điều này hiển nhiên vì trình biên dịch không thể thực hiện bất kỳ kiểm tra nào về việc sử dụng tham số trong phần thân phương thức).

Làm cách nào để tránh cảnh báo khi truy cập phương thức thông qua giao diện?

+0

Có liên quan (không có câu trả lời) http://stackoverflow.com/questions/15518302/java-varargs-in-interface – Tunaki

Trả lời

7

Không có cách nào để tránh cảnh báo này, vì không có cách nào để xác định một giao diện an toàn có phương pháp varargs chung.

Triển khai khác CollectiorIF có thể lạm dụng thông số, hiển thị bất kỳ người gọi nào là CollectorIF.addAll() dễ bị tấn công bởi hành vi thời gian chạy lạ. Bạn có thể tạo ra một trường hợp giao diện và các phương thức không cuối cùng nên cho phép @SafeVarargs (và yêu cầu các phương thức thực hiện/ghi đè được chú thích tương tự), nhưng hiện tại các nhà phát triển Java đã đưa ra quyết định có ý thức không hỗ trợ mẫu đó.

Các JLS cung cấp một nền ít hơn:

Các chú thích là không thể sử dụng phương pháp trọng nơi xảy ra. Thừa kế chú thích chỉ hoạt động trên các lớp (không phải các phương thức, các giao diện hoặc các hàm tạo), vì vậy chú thích @ SafeVarargs kiểu không thể được truyền qua các phương thức mẫu trong các lớp hoặc thông qua các giao diện.

~JLS §9.6.4.7

Trong khi đó bạn có hai lựa chọn; bỏ qua cảnh báo hoặc cấu trúc lại API của bạn.

Tái cấu trúc API của bạn thực sự có khả năng là chính xác những gì bạn muốn, vì các phương pháp vararg chung chỉ nên được sử dụng làm cầu nối cho việc triển khai thực sự đúng, chung chung. Thay vì xác định nó như là một phần của giao diện của bạn (và do đó yêu cầu tất cả các triển khai thực hiện nó) cung cấp nó như một phương thức tiện ích tĩnh, do đó làm cho API của giao diện nhỏ hơn trong khi vẫn cho người gọi sự linh hoạt để sử dụng các vararg. Theo Java 8, phương thức tiện ích thậm chí có thể được định nghĩa trong giao diện.

@SafeVarargs 
public static <T> void addAll(CollectorIF<T> collector, T... values) { 
    collector.addAll(Arrays.asList(values)); 
} 

giao diện của bạn sau đó cần xác định một phương pháp addAll(Iterable<T> values) cho phép implementors tránh thế giới crufty của varargs generic hoàn toàn.

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