Why can't static methods be abstract in Java

2018-12-31 15:05发布

The question is in Java why can't I define an abstract static method? for example

abstract class foo {
    abstract void bar( ); // <-- this is ok
    abstract static void bar2(); //<-- this isn't why?
}

24条回答
梦寄多情
2楼-- · 2018-12-31 15:39

I believe I have found the answer to this question, in the form of why an interface's methods (which work like abstract methods in a parent class) can't be static. Here is the full answer (not mine)

Basically static methods can be bound at compile time, since to call them you need to specify a class. This is different than instance methods, for which the class of the reference from which you're calling the method may be unknown at compile time (thus which code block is called can only be determined at runtime).

If you're calling a static method, you already know the class where it's implemented, or any direct subclasses of it. If you define

abstract class Foo {
    abstract static void bar();
}

class Foo2 {
    @Override
    static void bar() {}
}

Then any Foo.bar(); call is obviously illegal, and you will always use Foo2.bar();.

With this in mind, the only purpose of a static abstract method would be to enforce subclasses to implement such a method. You might initially think this is VERY wrong, but if you have a generic type parameter <E extends MySuperClass> it would be nice to guarantee via interface that E can .doSomething(). Keep in mind that due to type erasure generics only exist at compile time.

So, would it be useful? Yes, and maybe that is why Java 8 is allowing static methods in interfaces (though only with a default implementation). Why not abstract static methods with a default implementation in classes? Simply because an abstract method with a default implementation is actually a concrete method.

Why not abstract/interface static methods with no default implementation? Apparently, merely because of the way Java identifies which code block it has to execute (first part of my answer).

查看更多
孤独总比滥情好
3楼-- · 2018-12-31 15:40

You can't override a static method, so making it abstract would be meaningless. Moreover, a static method in an abstract class would belong to that class, and not the overriding class, so couldn't be used anyway.

查看更多
栀子花@的思念
4楼-- · 2018-12-31 15:43

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, along with default methods static methods are also allowed in an interface. 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.

A nice example of this is:

list.sort(ordering);

instead of

Collections.sort(list, ordering);

Another example of using static methods is also given in 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));
    }    
}
查看更多
人气声优
5楼-- · 2018-12-31 15:45

Because 'abstract' means the method is meant to be overridden and one can't override 'static' methods.

查看更多
妖精总统
6楼-- · 2018-12-31 15:47

The abstract annotation to a method indicates that the method MUST be overriden in a subclass.

In Java, a static member (method or field) cannot be overridden by subclasses (this is not necessarily true in other object oriented languages, see SmallTalk.) A static member may be hidden, but that is fundamentally different than overridden.

Since static members cannot be overriden in a subclass, the abstract annotation cannot be applied to them.

As an aside - other languages do support static inheritance, just like instance inheritance. From a syntax perspective, those languages usually require the class name to be included in the statement. For example, in Java, assuming you are writing code in ClassA, these are equivalent statements (if methodA() is a static method, and there is no instance method with the same signature):

ClassA.methodA();

and

methodA();

In SmallTalk, the class name is not optional, so the syntax is (note that SmallTalk does not use the . to separate the "subject" and the "verb", but instead uses it as the statemend terminator):

ClassA methodA.

Because the class name is always required, the correct "version" of the method can always be determined by traversing the class hierarchy. For what it's worth, I do occasionally miss static inheritance, and was bitten by the lack of static inheritance in Java when I first started with it. Additionally, SmallTalk is duck-typed (and thus doesn't support program-by-contract.) Thus, it has no abstract modifier for class members.

查看更多
墨雨无痕
7楼-- · 2018-12-31 15:47

You can do this with interfaces in Java 8.

This is the official documentation about it:

https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html

查看更多
登录 后发表回答