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)可能会出现的问题.会有什么害处?
可能重复:
Map.get(Object key)不是(完全)泛型的
原因是什么我们为什么要包含(Object o)而不是contains(E e)?
正如大家都可以看到的那样,类型为E的模板化java.util.List的contains方法没有模板化:它Object取而代之.有谁知道为什么?
在什么情况下会List<String>返回真实的myList.contains(new OtherNonString())?如果我没有弄错,永远不会,除非它被比较的对象具有类型E作为祖先(在我的字符串示例中由于String是最终的不可能)
是否只是为了保持与仿制前版本的向后兼容性?我错过了一个有意义的用例吗?如果它只是为了向后兼容,为什么不弃用contains(Object)并创建一个contains(E)?
编辑:
我之前的一些子问题已得到解答.作为参考,也请检查这个问题
可能重复:
Java泛型:为什么Map.get()忽略类型?
有人可以解释为什么使用Map定义
V put(K key,V value);
V get(Object key);
Run Code Online (Sandbox Code Playgroud)
为什么get没有定义为:
V get(K key)
Run Code Online (Sandbox Code Playgroud)
同样,为什么这些方法键入的Object,而不是K和V分别?
boolean containsKey(Object key); // Why not K?
boolean containsValue(Object value); // Why not V?
Run Code Online (Sandbox Code Playgroud)
这是一个向后兼容的东西(1.5之前的版本)?
由于Map.get()不是完全通用的,我们经常会发现开发人员传递不同类型的对象(以及bug)的情况.当我们开始使用其他团队的工件/服务时,此类案例的频率上升.Map.get(Object key)不是(完全)泛型的原因是什么原因解释了为什么get()不是完全通用的.
由于我们实际上没有属于不同类型的两个对象的用例,但是"语义上"相等,因此使用Map.get()版本将真正帮助我们在编译时识别这些错误.是否存在可用于生产的任何API?
可能重复:
Map.get(Object key)不是(完全)泛型的原因是什么
为什么Java的TreeSet <E> remove(Object)不带E
为什么HashSet不限制E的参数类型:
public boolean contains(Object o)
public boolean remove(Object o)
Run Code Online (Sandbox Code Playgroud)
就像它对add()一样
public boolean add(E e)
Run Code Online (Sandbox Code Playgroud)
我的意思是如果编译器强制只添加类型E的对象,那么该集合不能包含/删除任何其他类型
我有一个<p:dataTable>每行都有一个像这样的 inputText :
<p:dataTable ... rowIndexVar="row">
<p:column>
<p:inputText value="#{myBean.items[row + 1]}" />
</p:column>
</p:dataTable>
Run Code Online (Sandbox Code Playgroud)
该items属性是Map<Long, String>:
private Map<Long, String> items = new HashMap<Long, String>();
Run Code Online (Sandbox Code Playgroud)
当我提交一些数据并手动遍历地图时,它显然有效:
Iterator itr = items.entrySet().iterator();
while (itr.hasNext()) {
Map.Entry e = (Map.Entry) itr.next();
System.out.println("key: " + e.getKey() + " " + "value: " + e.getValue());
}
Run Code Online (Sandbox Code Playgroud)
我得到:
键:1 值:item1 键:2 值:item2 键:3 值:item3 键:4 值:item4
但是,当我尝试通过键获取特定项目时
String item = items.get(1);
Run Code Online (Sandbox Code Playgroud)
然后我得到一个null. 根据地图的内容,我应该得到item1. 这是怎么引起的,我该如何解决?
Android SparseIntArray的API文档打开:
SparseIntArrays将整数映射到整数.
我很好奇,那么,为什么它没有实现Map <Integer,Integer>.
在我看来,所有需要的是一些不同的方法名称,一些简单的额外方法,以及一些禁止null键和值的代码......当然,没有任何EnumMap无法处理的优雅.我忽略了什么吗?
这并非旨在向Android API的设计者轻扫.通常当我想到这样的事情时,事实证明这是一个很好的理由,我学到了一些关于语言或平台的知识.
为什么Map<K,V>,get()使用Object参数定义:
V get(Object key)
Run Code Online (Sandbox Code Playgroud)
而不是通用的参数:
V get(K key)
Run Code Online (Sandbox Code Playgroud)
?
当我在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) 下面的代码编译没有错误...一次我会更喜欢它失败:/
Map <Character, Double> m = new HashMap <Character, Double>();
m.get(new String());
Run Code Online (Sandbox Code Playgroud)
由于编译器知道此映射中使用的键是Character类型,因此使用String键应标记为不正确.
我错过了什么?