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

时间:2017-05-25 10:20:34

标签: java language-lawyer

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

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

2 个答案:

答案 0 :(得分:6)

静态接口方法Aren由子类

继承

您无法通过实例访问接口的静态方法。你必须静态访问它们。这与允许通过实例访问静态方法的类略有不同,但通常标记为代码气味;应静态访问静态方法。

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

  

8.4.8. Inheritance, Overriding, and Hiding

     

...

     

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

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

代码选项

因此,正如代码现在一样,您需要静态访问该方法:

{0.0=Udisk price: 0.0 capacity: 0, 1.0=Udisk price: 1.0 capacity: 1, 
2.0=Udisk price: 2.0 capacity: 2, 3.0=Udisk price: 3.0 capacity: 3, 
4.0=Udisk price: 4.0 capacity: 4, 5.0=Udisk price: 5.0 capacity: 5, 
6.0=Udisk price: 6.0 capacity: 6, 7.0=Udisk price: 7.0 capacity: 7, 
8.0=Udisk price: 8.0 capacity: 8, 9.0=Udisk price: 9.0 capacity: 9} 10

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

AWD.isRearWheelDrive()
但是,即使这看起来有点奇怪。看起来您可能希望默认方法覆盖超级接口中的某些非默认方法。也就是说,你可能想要这样的东西:

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

答案 1 :(得分:1)

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

中指定
  

如果表单是 ExpressionName . [TypeArguments] 标识符主要 {{1 [TypeArguments] Identifier ,然后编译时声明不能是接口中声明的.方法,否则会发生编译时错误。

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

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