我了解使用情况&两者的动机 - isInstance是instanceOf的Runtime等价物,但为什么我们有两种方法呢? 为什么我们不能有一个适用于这两种情况的instanceof关键字的通用实现?
例如,这是目前使用的方式:
public Collection<String> extract(Collection<?> coll) {
Collection<String> result = new ArrayList<String>();
for (Object obj : coll) {
if (obj instanceof String) {
result.add((String) obj);
}
}
return result;
}
public <T> Collection<T> extract(Collection<?> coll, Class<T> type) {
Collection<T> result = new ArrayList<T>();
for (Object obj : coll) {
if (type.isInstance(obj)) {
result.add((T) obj);
}
}
return result;
}
所以,我的问题是为什么我们不能有一个适用于上面第二个例子的instanceof运算符的泛型实现如下? (即为什么它不能在运行时解析类型?)
public <T> Collection<T> extract(Collection<?> coll, Class<T> type) {
Collection<T> result = new ArrayList<T>();
for (Object obj : coll) {
if (obj instanceof type) {
result.add((T) obj);
}
}
return result;
}
答案 0 :(得分:4)
一些背景知识:
instanceof
关键字/语法来自Java 1.0(IIRC)的Java。
在Java 1.1中引入了Class.isInstance
方法(根据javadoc)。
泛型是在Java 1.5(又名5.0)中引入的,尽管你不需要泛型来使你的例子有效。
instanceof的语法是<expr> 'instanceof' <type>
。为了支持您的建议,他们必须将其更改为<expr> 'instanceof' <type> | <expr>
。这有几个问题:
它可能会引入语法歧义。 (人们必须进行全面分析以确定是否属于这种情况。)
它可能会引入语义歧义。问题有点模糊,但是类型名称和变量名称位于不同的名称空间中,因此可以同时拥有一个变量和一个名为Something
的类。如果你这样做,obj instanceof Something
是指变量还是类?那么obj instanceof Something.class
呢?
另一个问题是,这种“增强”对典型程序员编写正确代码的能力影响不大。基本上,这是一个美容变化。因此,没有真正的理由进行改变。
现在我不知道Java团队是否考虑过这个选项。 (你必须问他们!)。如果他们这样做了,我不知道他们为什么拒绝它。但无论这些问题的答案是什么,Java都不会以这种方式工作......你只需要忍受它。
(如果还有另一个用于Java 9的“项目硬币”,你可以提出这个想法,但坦率地说,我认为它不会得到太多的支持。许多更有价值的想法都未能成功。)
1)通过语法模糊,你的意思是语法会变得复杂吗?如你所示,应该可以用这种方式编写解析语法。
没有。我的意思是语法可能含糊不清;即,给定的话语可以用两种不同的方式解析,意思是两种不同的东西。然后,您需要一些额外的规则(除了语法)来整理哪个解析是正确的。
2)如果第二个注释中的名称解析引入了语义歧义,为什么不能用适当的命名空间(变量或类型)限定名称
问题在于,这是规范编写者指定的所有语言复杂性,编译器编写者要实现的,以及程序员要理解的。
真正的好处是什么?只是一点句法“优雅”......当你考虑在不同层面发挥作用的特殊规则使其“有效”时,它实际上并不像看起来那么优雅。