Why can't I define a static method in a Java interface?

后端 未结 24 1088
没有蜡笔的小新
没有蜡笔的小新 2020-11-22 05:44

EDIT: As of Java 8, static methods are now allowed in interfaces.

Here\'s the example:

public interface IXMLizable         


        
相关标签:
24条回答
  • 2020-11-22 06:24

    I think java does not have static interface methods because you do not need them. You may think you do, but... How would you use them? If you want to call them like

    MyImplClass.myMethod()
    

    then you do not need to declare it in the interface. If you want to call them like

    myInstance.myMethod()
    

    then it should not be static. If you are actually going to use first way, but just want to enforce each implementation to have such static method, then it is really a coding convention, not a contract between instance that implements an interface and calling code.

    Interfaces allow you to define contract between instance of class that implement the interface and calling code. And java helps you to be sure that this contract is not violated, so you can rely on it and don't worry what class implements this contract, just "someone who signed a contract" is enough. In case of static interfaces your code

    MyImplClass.myMethod()
    

    does not rely on the fact that each interface implementation has this method, so you do not need java to help you to be sure with it.

    0 讨论(0)
  • 2020-11-22 06:25

    An interface can never be dereferenced statically, e.g. ISomething.member. An interface is always dereferenced via a variable that refers to an instance of a subclass of the interface. Thus, an interface reference can never know which subclass it refers to without an instance of its subclass.

    Thus the closest approximation to a static method in an interface would be a non-static method that ignores "this", i.e. does not access any non-static members of the instance. At the low-level abstraction, every non-static method (after lookup in any vtable) is really just a function with class scope that takes "this" as an implicit formal parameter. See Scala's singleton object and interoperability with Java as evidence of that concept. And thus every static method is a function with class scope that does not take a "this" parameter. Thus normally a static method can be called statically, but as previously stated, an interface has no implementation (is abstract).

    Thus to get closest approximation to a static method in an interface, is to use a non-static method, then don't access any of the non-static instance members. There would be no possible performance benefit any other way, because there is no way to statically link (at compile-time) a ISomething.member(). The only benefit I see of a static method in an interface is that it would not input (i.e. ignore) an implicit "this" and thus disallow access to any of the non-static instance members. This would declare implicitly that the function that doesn't access "this", is immutate and not even readonly with respect to its containing class. But a declaration of "static" in an interface ISomething would also confuse people who tried to access it with ISomething.member() which would cause a compiler error. I suppose if the compiler error was sufficiently explanatory, it would be better than trying to educate people about using a non-static method to accomplish what they want (apparently mostly factory methods), as we are doing here (and has been repeated for 3 Q&A times on this site), so it is obviously an issue that is not intuitive for many people. I had to think about it for a while to get the correct understanding.

    The way to get a mutable static field in an interface is use non-static getter and setter methods in an interface, to access that static field that in the subclass. Sidenote, apparently immutable statics can be declared in a Java interface with static final.

    0 讨论(0)
  • 2020-11-22 06:26

    What is the need of static method in interface, static methods are used basically when you don't have to create an instance of object whole idea of interface is to bring in OOP concepts with introduction of static method you're diverting from concept.

    0 讨论(0)
  • 2020-11-22 06:27

    Suppose you could do it; consider this example:

    interface Iface {
      public static void thisIsTheMethod();
    }
    
    class A implements Iface {
    
      public static void thisIsTheMethod(){
        system.out.print("I'm class A");
      }
    
    }
    
    class B extends Class A {
    
      public static void thisIsTheMethod(){
        System.out.print("I'm class B");
      } 
    }
    
    SomeClass {
    
      void doStuff(Iface face) {
        IFace.thisIsTheMethod();
        // now what would/could/should happen here.
      }
    
    }
    
    0 讨论(0)
  • 2020-11-22 06:29

    Java 8 permits static interface methods

    With Java 8, interfaces can have static methods. They can also have concrete instance methods, but not instance fields.

    There are really two questions here:

    1. Why, in the bad old days, couldn't interfaces contain static methods?
    2. Why can't static methods be overridden?

    Static methods in interfaces

    There was no strong technical reason why interfaces couldn't have had static methods in previous versions. This is summed up nicely by the poster of a duplicate question. Static interface methods were initially considered as a small language change, and then there was an official proposal to add them in Java 7, but it was later dropped due to unforeseen complications.

    Finally, Java 8 introduced static interface methods, as well as override-able instance methods with a default implementation. They still can't have instance fields though. These features are part of the lambda expression support, and you can read more about them in Part H of JSR 335.

    Overriding static methods

    The answer to the second question is a little more complicated.

    Static methods are resolvable at compile time. Dynamic dispatch makes sense for instance methods, where the compiler can't determine the concrete type of the object, and, thus, can't resolve the method to invoke. But invoking a static method requires a class, and since that class is known statically—at compile time—dynamic dispatch is unnecessary.

    A little background on how instance methods work is necessary to understand what's going on here. I'm sure the actual implementation is quite different, but let me explain my notion of method dispatch, which models observed behavior accurately.

    Pretend that each class has a hash table that maps method signatures (name and parameter types) to an actual chunk of code to implement the method. When the virtual machine attempts to invoke a method on an instance, it queries the object for its class and looks up the requested signature in the class's table. If a method body is found, it is invoked. Otherwise, the parent class of the class is obtained, and the lookup is repeated there. This proceeds until the method is found, or there are no more parent classes—which results in a NoSuchMethodError.

    If a superclass and a subclass both have an entry in their tables for the same method signature, the sub class's version is encountered first, and the superclass's version is never used—this is an "override".

    Now, suppose we skip the object instance and just start with a subclass. The resolution could proceed as above, giving you a sort of "overridable" static method. The resolution can all happen at compile-time, however, since the compiler is starting from a known class, rather than waiting until runtime to query an object of an unspecified type for its class. There is no point in "overriding" a static method since one can always specify the class that contains the desired version.


    Constructor "interfaces"

    Here's a little more material to address the recent edit to the question.

    It sounds like you want to effectively mandate a constructor-like method for each implementation of IXMLizable. Forget about trying to enforce this with an interface for a minute, and pretend that you have some classes that meet this requirement. How would you use it?

    class Foo implements IXMLizable<Foo> {
      public static Foo newInstanceFromXML(Element e) { ... }
    }
    
    Foo obj = Foo.newInstanceFromXML(e);
    

    Since you have to explicitly name the concrete type Foo when "constructing" the new object, the compiler can verify that it does indeed have the necessary factory method. And if it doesn't, so what? If I can implement an IXMLizable that lacks the "constructor", and I create an instance and pass it to your code, it is an IXMLizable with all the necessary interface.

    Construction is part of the implementation, not the interface. Any code that works successfully with the interface doesn't care about the constructor. Any code that cares about the constructor needs to know the concrete type anyway, and the interface can be ignored.

    0 讨论(0)
  • 2020-11-22 06:33

    Why can't I define a static method in a Java interface?

    Actually you can in Java 8.

    As per Java doc:

    A static method is a method that is associated with the class in which it is defined rather than with any object. Every instance of the class shares its static methods

    In Java 8 an interface can have default methods and static methods. This makes it easier for us to organize helper methods in our libraries. We can keep static methods specific to an interface in the same interface rather than in a separate class.

    Example of default method:

    list.sort(ordering);
    

    instead of

    Collections.sort(list, ordering);
    

    Example of static method (from doc itself):

    public interface TimeClient {
        // ...
        static public ZoneId getZoneId (String zoneString) {
            try {
                return ZoneId.of(zoneString);
            } catch (DateTimeException e) {
                System.err.println("Invalid time zone: " + zoneString +
                    "; using default time zone instead.");
                return ZoneId.systemDefault();
            }
        }
    
        default public ZonedDateTime getZonedDateTime(String zoneString) {
            return ZonedDateTime.of(getLocalDateTime(), getZoneId(zoneString));
        }    
    }
    
    0 讨论(0)
提交回复
热议问题