什么是决定不具有的接口完全通用的get方法背后的原因java.util.Map<K, V>.
为了澄清这个问题,方法的签名是
V get(Object key)
代替
V get(K key)
我想知道为什么(同样的事情remove, containsKey, containsValue).
在我查看值的索引的通用数据结构之前,我想看看它是否this已经参数化的类型的实例.
但是当我这样做时Eclipse会抱怨:
@Override
public int indexOf(Object arg0) {
if (!(arg0 instanceof E)) {
return -1;
}
Run Code Online (Sandbox Code Playgroud)
这是错误消息:
无法对类型参数E执行instanceof检查.请改为使用其擦除对象,因为泛型类型信息将在运行时被擦除
有什么更好的方法呢?
它是否与旧的(非泛化)版本保持向后兼容Collection?还是有一个我错过的更细微的细节?我看到这个模式在removealso(remove(Object o))中重复,但是add被泛化为add(E e).
虽然经历了这个问题:" 如果一个对象包含一个链表内检查 ",我发现用户正试图通过一个字符串参数到包含类型链表的链表的方法:
LinkedList<LinkedList> list = new LinkedList<LinkedList>();
list.contains("String");
Run Code Online (Sandbox Code Playgroud)
这不会引发任何编译错误,因为'contains'方法接受java.lang.Object并允许向其传递字符串值.
所以,只是出于好奇,我想知道为什么这种方法选择接受"对象",当它可能已被限制为仅接受列表类型(就像添加).是不是打败了泛型的整个目的,即"在编译时更强的类型检查"?
我已经像这样实例化了我的HashMap:
Map<String, Integer> myHashMap = new HashMap<String, Integer>();
Run Code Online (Sandbox Code Playgroud)
的数据类型Key为String,因此当我尝试在地图中插入新的键值对并保持KeyInteger时,它将引发错误。
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实例化哈希映射时使用的数据类型相同的数据类型。
List接口的lastIndexOf()方法接受Object类型的参数.
但是,add()方法接受E类型的参数(这是在创建List时定义的List的泛型类型)因为add()只接受E,所以这会阻止开发人员(或用户)在编译时自己将任何不兼容的对象添加到列表中.
现在,Java doc说如果传递的对象不兼容,lastIndexOf()可以抛出ClassCastException.但是,当我在Eclipse Helios中运行以下代码时,我没有得到任何异常: -
package scjp.collection.list;
import java.util.ArrayList;
import java.util.List;
public class LastIndexOf {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("some");
list.add("thing");
list.add("at");
list.add("last");
list.add("and");
list.add("at");
list.add("again");
System.out.println(list.lastIndexOf("at"));
System.out.println(list.lastIndexOf(10)); // # 1
System.out.println(list.lastIndexOf(new LastIndexOf())); // # 2
}
}
Run Code Online (Sandbox Code Playgroud)
在第1行和第2行,我已将不兼容的对象传递给我的List类型为String的对象.但是,我得到的输出是: -
5
-1
-1
Run Code Online (Sandbox Code Playgroud)
我没有得到ClassCastException.
如果lastIndexOf()方法接受了E类型的对象而不是Object类型的对象,那么这只能在编译时被阻止.为什么不这样做?
Java创建者必须考虑到如果它接受E(而不是Object)可能会出现的问题.会有什么害处?
我注意到,很少有LinkedList操作采用Generic参数类型E,而少数采用'Object'作为参数.对于前者,
add(E e)
remove(Object o)
Run Code Online (Sandbox Code Playgroud)
是否有特定的理由这样做?为什么不使'删除'采用泛型类型E.(我知道在类型擦除后无关紧要,但只是想知道).
当我在JDK中看到Set.java文件时,
/**
*
* <p>This interface is a member of the
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
* Java Collections Framework</a>.
*
* @param <E> the type of elements maintained by this set
*
* @author Josh Bloch
* @author Neal Gafter
* @see Collection
* @see List
* @see SortedSet
* @see HashSet
* @see TreeSet
* @see AbstractSet
* @see Collections#singleton(java.lang.Object)
* @see Collections#EMPTY_SET
* @since 1.2
*/
public interface Set<E> extends Collection<E> {
/**
* @param e element to be …Run Code Online (Sandbox Code Playgroud) 对于ArrayList,我们有:
public boolean add(E e) {
Run Code Online (Sandbox Code Playgroud)
但要删除我们有:
public boolean remove(Object o) {
Run Code Online (Sandbox Code Playgroud)
为什么不呢?:
public boolean remove(E e) {
Run Code Online (Sandbox Code Playgroud) 在ArrayList API中,add()接受泛型参数类型的参数,但contains()和indexOf()接受Object类型的参数.
public class ArrayList<E> ...{
public boolean add(E e);
public boolean contains(Object o);
public int indexOf(Object o);
....
}
Run Code Online (Sandbox Code Playgroud)
所以我只是想知道它是否与Generics有关或它的设计是否一致?
我查看了Openjdk实现,但找不到任何具体原因.
java ×10
generics ×6
collections ×3
arraylist ×1
contains ×1
hashmap ×1
instanceof ×1
list ×1
map ×1
set ×1
typechecking ×1