【问题标题】:Why can't I access static methods of an interface using an instance variable为什么我不能使用实例变量访问接口的静态方法
【发布时间】:2017-10-25 23:01:08
【问题描述】:

为什么我不能使用实例变量访问接口的静态方法。

public class TestClass {
    public static void main(String[] args) {
        AWD a = new Car();
        a.isRearWheelDrive(); //doesn't compile
    }
}

interface AWD {
    static boolean isRearWheelDrive() {
        return false;
    }  
}

class Car implements AWD {
}

【问题讨论】:

标签: java language-lawyer


【解决方案1】:

子类不继承静态接口方法

您不能通过实例访问接口的静态方法。您必须静态访问它们。这与允许通过实例访问静态方法但通常被标记为代码异味的类有点不同;静态方法应该被静态访问。

这是因为类的静态方法是由子类继承的,而接口的静态方法不是。这在规范的§8.4.8 中有说明:

8.4.8. Inheritance, Overriding, and Hiding

类不从其超接口继承静态方法。

当您查找实例的可访问方法时,接口中的静态方法不在其中。

代码选项

所以,就像现在的代码一样,您需要静态访问该方法:

AWD.isRearWheelDrive()

但是,您似乎希望这是一个实例方法,在这种情况下,您可能应该使用返回 false 的默认方法:

interface AWD {
  default boolean isRearWheelDrive() {
    return false;
  }
}

不过,这似乎有点奇怪。似乎您可能希望该默认方法覆盖超级接口中的某些非默认方法。也就是说,你可能想要这样的东西:

  interface HasDriveWheels {
    boolean isRearWheelDrive();
  }

  interface AllWheelDrive extends HasDriveWheels {
    @Override
    default boolean isRearWheelDrive() {
      return false;
    }
  }

【讨论】:

  • @JoshyaTaylor 我怀疑 OP 知道这一点并在问为什么(这似乎是一个很好的问题,因为同样的限制不适用于类)。您是否在 Java 规范中找到任何具体的说明来说明这一点?
  • @Mena 推理与接口的纯粹存在相同:如果您允许以这种方式访问​​静态方法,您将再次遇到菱形问题。
  • 我仍在查看规范,但我怀疑这与如何找到调用的方法有关。过去,当接口没有静态方法时,就不会有“搜索对象类型的接口的静态方法”的语言;如果将静态方法添加到接口中,添加它意味着引入潜在的未来歧义。
  • @JoshuaTaylor here you go.
  • 我认为是8.4.8,“一个类不会从它的超接口继承static 方法。”我发现在另一个问题中,这可能不是一个骗局(它已经假设知道答案):stackoverflow.com/questions/29383083/….
【解决方案2】:

这是在The Java® Language Specification, §15.12.3. Compile-Time Step 3: Is the Chosen Method Appropriate?中指定的

如果表单是 ExpressionName . [TypeArguments] IdentifierPrimary . [TypeArguments] 标识符,那么编译时声明不能是接口中声明的static方法,否则会发生编译时错误。

回想起来,通过实例调用static 方法的能力几乎没有用处,甚至不如static 方法的继承。我很确定很多开发人员认为这是一个设计错误,只是出于兼容性原因才保留下来。

对于接口中static 方法的较新特性,不存在需要重复此错误的兼容性约束,因此,接口中static 方法的规则设计不同。这也是对旧代码兼容性影响最小的方案。

【讨论】:

    猜你喜欢
    • 2011-04-26
    • 2015-02-12
    • 2021-10-01
    • 1970-01-01
    • 2016-11-10
    • 2011-05-10
    • 1970-01-01
    • 2015-02-12
    • 1970-01-01
    相关资源
    最近更新 更多