为什么我不能在Java中“静态导入”一个“等于”方法?

2022-09-01 09:46:35

我喜欢在这里使用这种方法:

org.apache.commons.lang.ObjectUtils.equals(Object object1, Object object2)

唯一的缺点(例如,与Google Guava相比),是我无法静态导入该方法。即这是无用的:

import static org.apache.commons.lang.ObjectUtils.equals;

...因为我的Eclipse编译器在编写时无法正确链接该方法

equals(obj1, obj2);

错误是:

对象类型中的方法等于(对象)不适用于参数(...,...)

为什么?如果任何超类型中存在具有相同名称(但不是相同签名)的方法,我的静态导入方法是否不适用?这是否在 JLS 中正式指定?还是一些 Eclipse 编译器问题?

更新

这也不起作用:

import static org.apache.commons.lang.ObjectUtils.defaultIfNull;

public class Test {
  void test() {
    defaultIfNull(null, null);
    // ^^ compilation error here
  }

  void defaultIfNull() {
  }
}

javac 错误消息:

Test.java:5: defaultIfNull() in Test cannot be applied to (<nulltype>,<nulltype>)
defaultIfNull(null, null);
    ^
1 error

答案 1

冲突实际上是与 .所有类都是从中继承的,因此具有导致此冲突的方法。Object.equals()ObjectObject.equals()

您是按名称导入的,而不是按签名导入的。实际上,您无法导入因此而命名的静态方法。或者更确切地说,您可以导入它,但不能使用它。我同意这应该有效。equals

(我的评论是我自己的答案。


答案 2

根据 Java 语言规范

  1. 如果单静态导入声明导入简单名称为 n 的成员,并且编译单元还包含导入简单名称为 n 的类型的单类型导入声明,则会发生编译时错误。(即使两个声明都引用同一类型,也会发生此错误,理由是使用两种不同的机制来冗余导入同一类型会令人困惑。
  2. 如果单静态导入声明导入的简单名称为 n 的成员,并且编译单元还声明了简单名称为 n 的顶级类型,则会发生编译时错误。

因此,在您的情况下,上面提到的第2点是您遇到编译时错误的原因。因此,即使方法签名不同,如果名称相同,这也是编译时错误。

静态导入 JSRJLS