5

我了解这两者的用法和动机 - isInstance 是运行时等效于 instanceOf。但是,为什么我们有两种方法?为什么我们不能有一个适用于这两种情况的 instanceof 关键字的通用实现?

例如,这是当前使用这些的方式:

1)实例

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;
}

2)isInstance

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;
}
4

1 回答 1

4

一些背景:

  • 关键字 / 语法来自instanceofJava 1.0 (IIRC)。

  • Class.isInstance方法是在 Java 1.1 中引入的(根据 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 有另一个“Project Coin”,你可能会提出这个想法,但坦率地说,我不认为它会得到太多支持。许多更有价值的想法都未能成功。)


1)语法歧义是指语法会变得复杂吗?正如您所展示的那样,应该可以这样编写解析语法。

不,我的意思是语法可能是模棱两可的;即,可以以两种不同的方式解析给定的话语,这意味着两种不同的事物。然后,您需要一些额外的规则(除了语法之外)来确定哪个解析是正确的。

2)如果第二条评论中的名称解析引入语义歧义,为什么不能用适当的命名空间(变量或类型)限定名称

问题在于,对于规范编写者要指定、编译器编写者要实现以及程序员要理解,这都是额外的语言复杂性。

真正的好处是什么?只是一点句法“优雅”......当您考虑在各个级别发挥作用以使其“工作”的特殊规则时,实际上并不像看起来那么优雅。

于 2013-04-02T06:25:27.660 回答