Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't I access static methods of an interface using an instance variable

Why can't I access static methods of an interface using an instance variable.

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 {
}
like image 896
chamina Avatar asked May 25 '17 10:05

chamina


2 Answers

Static Interface Methods Aren't Inherited by Subclasses

You can't access static methods of interfaces through instances. You have to access them statically. This is a bit different from classes where accessing a static method through an instance is allowed, but often flagged as a code smell; static methods should be accessed statically.

That's because static methods of classes are inherited by subclasses, but static methods of interfaces aren't. That's stated in §8.4.8 of the specification:

8.4.8. Inheritance, Overriding, and Hiding

A class does not inherit static methods from its superinterfaces.

When you are looking up the accessible methods for the instance, the static method from the interface isn't among them.

Options for the code

So, as the code is now, you need to access the method statically:

AWD.isRearWheelDrive()

However, it seems like you want this to be an instance method, in which case you should probably be using a default method that returns false:

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

Even that seems a little bit odd, though. It seems like you'd probably want that default method to be overriding some non-default method in a super-interface. That is, you probably want something like:

  interface HasDriveWheels {
    boolean isRearWheelDrive();
  }

  interface AllWheelDrive extends HasDriveWheels {
    @Override
    default boolean isRearWheelDrive() {
      return false;
    }
  }
like image 122
Joshua Taylor Avatar answered Oct 09 '22 20:10

Joshua Taylor


This is specified in The Java® Language Specification, §15.12.3. Compile-Time Step 3: Is the Chosen Method Appropriate?

If the form is ExpressionName . [TypeArguments] Identifier or Primary . [TypeArguments] Identifier, then the compile-time declaration must not be a static method declared in an interface, or a compile-time error occurs.

In retrospect, the ability to invoke a static method through an instance is of little use, even less than the inheritance of static methods. I’m quite sure that a lot of developers consider it a design mistake that is only kept due to compatibility reasons.

For the newer feature of static methods in an interface, there was no compatibility constraint that required repeating this mistake, hence, the rules for static methods in interfaces were designed differently. This is also the solution with the smallest impact on compatibility with old code.

like image 38
Holger Avatar answered Oct 09 '22 20:10

Holger