【问题标题】:Why are static imports of static methods with same names legal?为什么同名静态方法的静态导入是合法的?
【发布时间】:2012-10-12 03:39:24
【问题描述】:

假设我们有这些包和类:

package p1;

public class A1 {
    public static void a() {}
}

package p2;

public class A1 {
    public static void a() {}
}

package p3;

import static p1.A1.a;
import static p2.A1.a;

public class A1 {
    public static void test() {

    }
}

我想知道,为什么在包p3 中方法的静态导入是合法的(不会导致编译时错误)?我们将无法在test() 方法中进一步使用它们,因为这样使用会导致编译时错误。

为什么它与普通的类导入不同。假设我们想从包 p1p2 导入类 A1p3

package p3;
import p1.A1;
import p2.A1;

这样的导入是非法的,会导致编译时错误。

【问题讨论】:

  • 因为包和类组合唯一地将一种方法与另一种方法区分开来。
  • @duffymo - 他特别问为什么静态导入方法时没有名称冲突,您没有解决。
  • 我想是的。区分 betweek a.b.c 和 a.d.c 没有问题;编译器也没有。

标签: java import static-import


【解决方案1】:

方法的静态导入的歧义可以在方法调用时解决。

例如,如果您有两个方法的静态导入,如下所示:

void frobnicate(int i);
// and
void frobnicate(boolean b);

然后您可以导入并使用两者,因为编译器可以根据您传入的参数(frobnicate(1) 调用第一个参数,frobnicate(true) 调用第二个参数)来判断要使用哪个。

对于类,这是不可能的:仅Foobar a; 不足以告诉您需要两个Foobar 中的哪一个。

另请注意,单个静态导入可以导入多个名称。根据relevant section of the JLS(强调我的):

single-static-import 声明从类型中导入所有具有给定简单名称的可访问静态成员。

例如,如果上面的两个 frobnicate 方法位于同一类中,则单个 static 导入可以同时导入它们。

【讨论】:

  • 有趣的事实:Groovy 也允许这样做,但是如果你像我一样不够小心,它会在运行时向你抛出 groovy.lang.MissingMethodException: No signature of method。它还将在错误消息中列出Possible solutions,其中将包含隐藏您首先尝试调用的方法名称。我花了一个小时才弄明白。
  • 当编译器“知道”两个同名的静态方法具有相同的签名时,问题仍然是为什么编译器允许这样做。
  • @DávidHorváth 如果您可以重现这种歧义,那么我建议您提交一个错误。这听起来绝对像是编译器应该阻止的。
【解决方案2】:

这是因为您将所有这些类命名为相同的东西。每次调用此静态方法时,它都会查找最本地的类,在本例中是 p3 中的 A1,它不包含静态方法 a()。永远记住一个类名应该是唯一的,并且不能与另一个相同。

【讨论】:

    【解决方案3】:

    我猜测,不受语言规范支持,方法可以重载,但字段/类型不能;因此java允许从不同的类中导入同名的方法。

    但是同一个类中不能存在两个相同签名的方法;进口也不应该允许它们。

    即使这两种方法有不同的签名,这仍然是一个坏主意。一个名字的含义很重要,它应该是清晰的。我们可以处理来自 1 个类的重载方法,但跨类“重载”是一种延伸。

    【讨论】:

      猜你喜欢
      • 2010-09-30
      • 2023-03-09
      • 1970-01-01
      • 2014-11-03
      • 1970-01-01
      • 1970-01-01
      • 2012-12-13
      • 2011-12-11
      • 1970-01-01
      相关资源
      最近更新 更多