2009-07-13 40 views
17

Trong Java, có thể khai báo một trường/biến có kiểu là nhiều giao diện không? Ví dụ: tôi cần khai báo số Map cũng là Serializable. Tôi muốn đảm bảo biến tham chiếu đến một bản đồ tuần tự hóa. Giao diện Map không mở rộng Serializable, nhưng hầu hết các triển khai của MapSerializable.Java, khai báo biến với nhiều giao diện?

Tôi chắc chắn câu trả lời là không.

Theo dõi: Tôi hoàn toàn nhận thức được việc tạo giao diện mới mở rộng cả MapSerializable. Điều này sẽ không hoạt động như hiện tại (chẳng hạn như HashMap) không triển khai giao diện mới của tôi.

Trả lời

7

Không cần để khai báo trường/biến như thế. Đặc biệt vì nó chỉ có thể được kiểm tra thời gian chạy và không biên dịch thời gian. Tạo một setter và báo cáo lỗi nên Map đã truyền không thực thi Serializable.

Các câu trả lời đề xuất rằng bạn tạo giao diện của riêng bạn tất nhiên là không thực tế vì chúng sẽ chủ động cấm gửi những thứ có trên Bản đồ và có thể tuần tự chứ không phải giao diện đặc biệt của bạn.

+0

Ngay cả khi 'Bản đồ' thực hiện' Serializable', nó không nhất thiết có nghĩa là nó có thể nối tiếp được. Nhưng có khả năng tuần tự hóa Java là một vấn đề thời gian chạy trong Java. –

+0

Thật không may cho Java, đây là câu trả lời đúng và xứng đáng để được ở trên cùng. – hythlodayr

+0

Bạn đã bỏ lỡ phần quan trọng của câu trả lời của tôi ... Bạn chấp nhận Bản đồ và THEN kiểm tra xem đối tượng có phải là một thể hiện của Serializable hay không. Tất nhiên bạn có thể làm điều đó theo cách khác nhưng sau đó bạn sẽ nhận được một giao diện không thực sự cho người dùng biết bạn muốn loại bộ sưu tập nào. – Fredrik

6
public interface MyMap extends Map, Serializable { 
} 

sẽ xác định giao diện mới là liên minh MapSerializable.

Bạn rõ ràng là phải sau đó cung cấp một thực hiện phù hợp với điều này (ví dụ MyMapImpl) và sau đó bạn có thể cung cấp tài liệu tham khảo biến kiểu MyMap (hoặc Map, hoặc Serializable, tùy theo yêu cầu).

Để giải quyết rõ ràng của bạn, bạn không thể trang bị thêm hành vi (ví dụ: bản đồ có thể tuần tự hóa). Bạn để có giao diện và một số triển khai thích hợp.

+2

Tôi giả định rằng anh ấy muốn chỉ định các đối tượng hiện có cho biến, ví dụ: một đối tượng HashMap. – skaffman

+2

Tôi nghĩ rằng anh ấy muốn có một bản đồ có thể tuần tự hóa như một chữ ký có thể thay đổi, nhưng vẫn có thể sử dụng HashMap, TreeMap, vv .. tức là, MyMap map = new HashMap(); tôi sẽ không làm việc. – JeeBee

3

Bạn có thể đạt được điều này bằng cách làm cho giao diện của riêng mình, mà mở rộng các giao diện bạn muốn

public interface SerializableMap<K, V> extends Map<K, V>, Serializable { 

} 
11

Bạn có thể làm điều đó với Generics, nhưng nó không đẹp:

class MyClass<T,K,V extends Serializable & Map<K,V>> { 

    T myVar; 

} 
+1

Có thể muốn thêm K & V vào đó. –

+0

Bạn cũng thường cần nhiều sự xấu xí trong cách bạn sử dụng. –

+0

Vâng, nó sẽ hút một cái lớn, và tôi thà kéo móng tay của riêng mình hơn là sử dụng những gì tôi đã viết ở trên, nhưng người đàn ông kia đang trả tiền ở đây. – skaffman

0

Bạn không thể thực sự làm điều đó nếu bạn muốn tiếp tục sử dụng hiện tại Map triển khai.

Một thay thế sẽ là để tạo ra một lớp helper, và thêm một phương pháp như thế này một:

public static Serializable serializableFromMap(Map<?, ?> map) { 
    if (map instanceof Serializable) { 
     return (Serializable)map; 
    } 
    throw new IllegalArgumentException("map wasn't serializable"); 
} 
2

Tôi đã bỏ phiếu lên câu trả lời của Brian, nhưng muốn thêm một chút cấp cao nghĩ ..

Nếu bạn xem qua SDK, bạn sẽ thấy rằng hiếm khi (nếu có) vượt qua các đối tượng thu thập thực tế.

Lý do cho điều đó là không phải là một ý tưởng hay. Bộ sưu tập cực kỳ không được bảo vệ.

Hầu hết thời gian bạn muốn tạo một bản sao trước khi chuyển nó đi và chuyển bản sao để mọi sửa đổi đối với bộ sưu tập sẽ không thay đổi môi trường cho một thứ khác dựa vào nó.Ngoài ra, luồng trở thành một cơn ác mộng - ngay cả với một bộ sưu tập đồng bộ!

Tôi đã nhìn thấy hai giải pháp, một là luôn trích xuất một mảng và chuyển nó. Đây là cách SDK thực hiện.

Cách khác là LUÔN LUÔN bọc các bộ sưu tập trong một lớp cha mẹ (Và tôi có nghĩa là đóng gói, không mở rộng). Tôi đã nhận được vào thói quen này và nó rất đáng giá trong khi. Nó không thực sự chi phí bất cứ điều gì bởi vì bạn không sao chép tất cả các phương pháp thu thập anyway (thực sự bạn hiếm khi trùng lặp bất kỳ của họ). Trong thực tế những gì bạn kết thúc làm là di chuyển "Tiện ích" chức năng từ các lớp khác được phân phối trên tất cả các mã của bạn vào lớp wrapper, đó là nơi mà nó nên có được ở nơi đầu tiên.

Bất kỳ phương pháp nào có chữ ký khớp với "phương pháp (bộ sưu tập, ...)" gần như chắc chắn sẽ là một phương pháp thành viên của bộ sưu tập đó, vì bất kỳ vòng lặp nào lặp lại trên bộ sưu tập.

Tôi chỉ phải vứt bỏ mọi thứ bây giờ và sau đó bởi vì đó là một trong những điều tôi không nhận được trong một thời gian (vì không ai vô địch khái niệm này). Nó luôn luôn có vẻ như nó sẽ có một số nhược điểm nhưng đã làm điều này trong một thời gian và nhìn thấy những vấn đề nó giải quyết và mã nó loại bỏ, tôi thậm chí không thể tưởng tượng bất kỳ hạn chế có thể bản thân mình, nó chỉ là tất cả tốt.

+0

Tôi đồng ý với điều này. Nó không rõ ràng với tôi tại sao chấp nhận tùy ý hiện tại 'Map' là mong muốn, chứ không phải là một số giao diện có ý nghĩa ngữ nghĩa cụ thể cho các mã trong tầm tay. –

6

Có thể thực hiện điều này sử dụng một số thủ thuật Generics:

public <T extends Map<?,?> & Serializable> void setMap(T map) 

Đoạn mã trên sử dụng Generics để buộc bạn phải vượt qua một bản đồ mà thực hiện cả hai giao diện. Tuy nhiên, lưu ý rằng hậu quả của việc này là khi bạn thực sự chuyển nó vào bản đồ, chúng có thể cần phải được đánh dấu là có thể tuần tự hóa hoặc loại bản đồ đã được tuần tự hóa. Nó cũng khá khó đọc hơn một chút. Tôi sẽ ghi lại rằng bản đồ phải được tuần tự hóa và thực hiện thử nghiệm cho nó.

0

Không, bạn sẽ cần phải truyền.

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