为什么Collection.remove(Object o)不是通用的?
似乎Collection<E>
可能有boolean remove(E o);
然后,当您意外地尝试Set<String>
从a中删除(例如)而不是每个单独的String时Collection<String>
,这将是编译时错误,而不是稍后的调试问题.
虽然经历了这个问题:" 如果一个对象包含一个链表内检查 ",我发现用户正试图通过一个字符串参数到包含类型链表的链表的方法:
LinkedList<LinkedList> list = new LinkedList<LinkedList>();
list.contains("String");
Run Code Online (Sandbox Code Playgroud)
这不会引发任何编译错误,因为'contains'方法接受java.lang.Object并允许向其传递字符串值.
所以,只是出于好奇,我想知道为什么这种方法选择接受"对象",当它可能已被限制为仅接受列表类型(就像添加).是不是打败了泛型的整个目的,即"在编译时更强的类型检查"?
例如:
scala> val l:List[String] = List("one", "two")
l: List[String] = List(one, two)
scala> l.contains(1) //wish this didn't compile
res11: Boolean = false
Run Code Online (Sandbox Code Playgroud)
在Java中以这种方式完成事情的原因的各种解释在这里似乎并不适用,因为Map和Set确实实现了类型安全版本contains
和朋友.有没有办法contains
在Seq上做一个类型安全的东西,不能把它克隆成一个Set?
来自javadocs:
public interface Cache<K,V> extends Function<K,V> {
//...
void invalidate(Object key);
//...
}
Run Code Online (Sandbox Code Playgroud)
为什么不将其呈现为通用方法:
void invalidate(K key);
Run Code Online (Sandbox Code Playgroud)
有技术原因,历史原因还是其他原因?
我已经像这样实例化了我的HashMap:
Map<String, Integer> myHashMap = new HashMap<String, Integer>();
Run Code Online (Sandbox Code Playgroud)
的数据类型Key
为String,因此当我尝试在地图中插入新的键值对并保持Key
Integer时,它将引发错误。
myHashMap.put(1L, "value");
Run Code Online (Sandbox Code Playgroud)
这意味着在put方法中,他们已经限制了的数据类型Key
。但是,当使用get
方法从映射中获取值时,它并不会检查的数据类型Key
。因此,如果我写这样的东西,它不会给出编译错误。
myHashMap.get(1L);
Run Code Online (Sandbox Code Playgroud)
我get
在Java Map界面中检查了该方法,其参数类型为Object
,因此这就是为什么它允许将任何Object用作put方法参数的原因。
V get(Object key)
Run Code Online (Sandbox Code Playgroud)
有什么方法可以限制在get
方法中作为参数传递的数据类型?
我传递的参数应具有与Key
实例化哈希映射时使用的数据类型相同的数据类型。
此方法和Map接口中的许多其他方法不是通用的.几乎任何键值都需要作为参数,它接受Object,即remove,get和containsKey.
知道为什么他们做出这个决定.我的假设是它是为了支持遗留代码,但对我来说,我认为这是一个弱势的立场.
任何人都可以向我提供一个特定的理由,为什么最好在这里接受Object而不是KeyType.
我最近被一个带有密钥类型的Map的bug所困Long
,但我试图将它与类型的密钥一起使用String
.我基本上有类似的东西:
Map<Long, Object> map;
...
String wrongType;
if (map.containsKey(wrongType)) {
// Do something
} else {
// Do something different
}
Run Code Online (Sandbox Code Playgroud)
因为映射中的所有键都是Long类型,所以代码总是执行else
块.
由于containsKey
和get
方法采用类型的参数,因此Object
可以接受任何旧类型的对象而不会抱怨.
我的困惑源于这样一个事实:在我们的系统中,同一个实体以两种不同的方式表示(有时作为a Long
,有时作为a String
); 我不能轻易改变这一点.有没有什么方法可以在开发时而不是在测试期间捕获这样的错误?也许是一个编译器标志或一些Eclipse选项,它更聪明一些我应该使用的方法containsKey
和get
方法(以及它们的类似物Set
...)
在Java中,Map接口定义为,
public interface Map<K,V> {
...
V get(Object key);
...
}
Run Code Online (Sandbox Code Playgroud)
为什么不?
V get(K key);
Run Code Online (Sandbox Code Playgroud)
我只是碰到了一个讨厌的bug,因为使用了错误的类型键.我认为泛型的目的是在编译期间尽早捕获类型错误.这会破坏这个目的吗?
从Java 6 TreeSet<E>
文档:
boolean remove(Object o):
Removes the specified element from this set if it is present.
Run Code Online (Sandbox Code Playgroud)
为什么这会接受Object而不是泛型E?唯一可以添加的对象是E类型,因此唯一的可移动类型应该是E类型.
可能重复:
Map.get(Object key)不是(完全)泛型Java Generics 的原因是什么
:为什么Map.get()忽略类型?
Java Map接口声明如下:
Interface Map<K,V>
Run Code Online (Sandbox Code Playgroud)
它有这样一种方法:
boolean containsKey(Object key)
Run Code Online (Sandbox Code Playgroud)
为什么不
boolean containsKey(K key)
呢?
相反,List接口有add方法,它接受泛型类型的参数而不是Object
:
boolean add(E e).
Run Code Online (Sandbox Code Playgroud)