isInstance& instanceof - 为什么没有通用方法?

时间:2013-04-02 05:47:30

标签: java class object rtti

我了解使用情况&两者的动机 - isInstance是instanceOf的Runtime等价物,但为什么我们有两种方法呢? 为什么我们不能有一个适用于这两种情况的instanceof关键字的通用实现?

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

1)的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;
}

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

1 个答案:

答案 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)如果第二个注释中的名称解析引入了语义歧义,为什么不能用适当的命名空间(变量或类型)限定名称

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

真正的好处是什么?只是一点句法“优雅”......当你考虑在不同层面发挥作用的特殊规则使其“有效”时,它实际上并不像看起来那么优雅。