2013-02-25 27 views
7

Xem xét giao diện UnaryFunction được xác định trong Hiệu quả Java chương generics.Tại sao an toàn để ngăn chặn cảnh báo không được kiểm soát này?

public interface UnaryFunction<T> { 
T apply(T arg); 
} 

và đoạn mã sau để trả lại UnaryFunction

// Generic singleton factory pattern 
private static UnaryFunction<Object> IDENTITY_FUNCTION = new UnaryFunction<Object>() { 
    public Object apply(Object arg) { return arg; } 
}; 

// IDENTITY_FUNCTION is stateless and its type parameter is 
// unbounded so it's safe to share one instance across all types. 
@SuppressWarnings("unchecked") 
public static <T> UnaryFunction<T> identityFunction() { 
    return (UnaryFunction<T>) IDENTITY_FUNCTION; 
} 

Tại sao là diễn viên của IDENTITY_FUNCTION để (UnaryFunction<T>) an toàn không?

Quyển sách nói về câu hỏi tôi đang hỏi nhưng tôi không thể theo logic ở đây. Chúng ta đang gọi hàm apply hoạt động nhận dạng ở đâu? tôi bối rối bởi vì đó là hàm trả về cùng một đối tượng được truyền vào nó mà không sửa đổi bất cứ thứ gì.

Dàn diễn viên của IDENTITY_FUNCTION để (UnaryFunction<T>) tạo ra một cảnh báo kiểm soát dàn diễn viên, như UnaryFunction<Object> không phải là một UnaryFunction<T> cho mỗi T. Nhưng chức năng nhận dạng là đặc biệt: nó trả về đối số của nó chưa sửa đổi, vì vậy chúng tôi biết rằng nó là an toàn để sử dụng nó như là một UnaryFunction<T> bất kể giá trị của T. Do đó, chúng tôi có thể tự tin chặn cảnh báo truyền không được chọn được tạo bởi lần truyền này. Khi chúng tôi đã thực hiện việc này, mã sẽ biên dịch không có lỗi hoặc cảnh báo .

+0

Câu hỏi phụ: bạn đang sử dụng sách nào và nó nói điểm của mã này là gì? – asteri

+0

@Jeff Hiệu quả java là tên sách và nó có trong chương generics, đặc biệt trong phần mô tả các chức năng chung. – Geek

Trả lời

3

Dàn diễn viên được an toàn đến nỗi chỉ như chức năng danh tính trả về đối tượng chính xác đã được truyền cho nó ở nơi đầu tiên. Như vậy, trong thời gian chạy, không có chuyên môn về thông số chung T có thể vi phạm dàn diễn viên.

Aka, bạn đang truyền một đối tượng làm loại riêng.

3

Với loại chô bôi

T apply(T arg); 

thực sự là

Object apply(Object arg); 

Bây giờ cho bản sắc

Abc x = ...; 
Abc y = IDENTITY.apply(x); 

người ta có thể giả định rằng nó luôn luôn là chính xác (tương đương với y = x;).

(Rất thực dụng.)

+0

'Áp dụng' ở đâu được gọi là mã được đề cập? – Geek

+0

Bất cứ khi nào identityFunction được áp dụng (.apply) kết quả được gán T IDENTITY.apply (T), thông thường không thể thực hiện được, vì tham số T không có ở thời gian chạy. –

1

identityFunction() chỉ trả về chính hàm đó, được sử dụng trên các đối tượng khác nhau.

Sau đây là một ví dụ sử dụng: cảnh báo an toàn

String result = identityFunction().apply("Hello"); 

Loại là rất quan trọng. Nó có bởi vì IDENTITY_FUNCTION được thực hiện sao cho trình biên dịch không thể đảm bảo rằng hàm trả về cùng kiểu với đầu vào. Xem xét việc thực hiện thay thế sau:

private static UnaryFunction<Object> CONST_FUNCTION = new UnaryFunction<Object>() { 
    public Object apply(Object arg) { return "Default"; } 
}; 

thi này luôn trả về một chuỗi, do đó, nó rõ ràng là không an toàn để trở lại nó như là một chức năng unary trên kiểu dữ liệu chung.

Trong trường hợp của chúng tôi (IDENTITY_FUNCTION), bằng chứng cho thấy kiểu trả về giống với loại đầu vào bên trong triển khai. Chúng tôi trả lại cùng một trường hợp, vì vậy nó được đảm bảo có cùng loại. Khi bạn loại bỏ cảnh báo an toàn loại, bạn nên chứng minh điều đó bằng chứng minh.

+0

-1 Khó hiểu. IdentityFunction() không trả về chính "function function", nó trả về chính _argument_. Tôi thấy không có lý do tại sao kết quả này, của loại T là "được sử dụng trên các đối tượng khác nhau". Trong ví dụ của bạn, nó là một String mà _cannot_ được _used_ trên các đối tượng khác nhau. – user949300

+1

@ user949300: 'identityFunction()' trả về một tham chiếu đến đối tượng được lưu trữ trong biến 'IDENTITY_FUNCTION'. Tham chiếu đó cho phép bạn gọi 'apply()', do đó 'identityFunction()' trả về hiệu quả chính hàm đó. Sẽ tốt hơn nếu các tên không giống nhau. Ex 'getIdentityFunction()' và 'IDENTITY_FUNCTION'. Dòng đầu tiên của câu trả lời là đề cập đến phương thức getter. – unholysampler

+0

cảm ơn - đã hiểu. Toàn bộ câu hỏi/hệ thống này là rất khó hiểu cho một cái gì đó mà không có gì :-). Tôi không thể "hoàn tác" downvote của tôi mặc dù cho đến khi bạn chỉnh sửa câu trả lời của bạn do những hạn chế trong StackOverflow. – user949300

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