Tôi đang viết một đơn giản HashMap
cache dựa trên đó hoạt động như sau:Java - Mở rộng HashMap - Object vs Generics hành vi
- Nếu yêu cầu
key
là trong bộ nhớ cache, trởvalue
của nó. - Nếu yêu cầu
key
không phải là ở đó, chạy một phương pháp sản xuấtvalue
dựa trênkey
, lưu trữ cả, trở vềvalue
.
Mã:
import java.util.HashMap;
abstract class Cache<K, V> extends HashMap<K, V> {
@Override
public V get(Object key) {
if (containsKey(key)) {
return super.get(key);
} else {
V val = getData(key);
put((K)key, val); // this is the line I'm discussing below
return val;
}
}
public abstract V getData(Object key);
}
Nó khá đơn giản và hoạt động tốt. Tuy nhiên, tôi ghét quyết định của Sun đối với get()
để tham số Object
làm đối số của nó chứ không phải K
. Tôi đã đọc đủ về nó để biết rằng nó có một số lý do đằng sau nó (mà tôi không đồng ý, nhưng đó là một câu chuyện khác).
Sự cố của tôi nằm trong dòng nhận xét, vì có vẻ như dàn diễn viên có không được chọn. Do loại tẩy xoá, không có cách nào tôi có thể kiểm tra xem key
có thuộc loại K
(cần thiết cho chức năng put()
thích hợp) và do đó, phương pháp dễ bị lỗi.
Một giải pháp sẽ là chuyển từ "là" thành "có mối quan hệ" HashMap
đẹp hơn và sạch sẽ hơn, nhưng sau đó Cache
không thể triển khai Map
. Mã này:
import java.util.HashMap;
import java.util.Map;
abstract class Cache<K, V> {
private final Map<K, V> map = new HashMap<K, V>();
public V get(K key) {
if (map.containsKey(key)) {
return map.get(key);
} else {
V val = getData(key);
map.put(key, val);
return val;
}
}
public abstract V getData(K key);
}
bất cứ ai có thể đưa ra bất kỳ khác (thậm chí hackish) giải pháp, vì vậy mà tôi có thể duy trì Cache
là một Map
và vẫn được an toàn trong các điều khoản của get(Object key)
và put(K key, V val)
loại?
Điều duy nhất tôi có thể nghĩ là tạo một phương pháp khác có tên là getValue(Key k)
sẽ ủy quyền cho get(Object key)
, nhưng sau đó tôi không thể buộc bất kỳ ai sử dụng phương pháp mới thay vì phương pháp thông thường.
Bạn có thể triển khai 'getA' hoặc' myget' Bạn không thể thay đổi hành vi của Bản đồ.get() vì bạn không thể ép buộc mã sử dụng giao diện thay vì lớp của bạn trực tiếp để được biên dịch lại. –