Why can't static methods be abstract in Java?

Viewed 317811

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?
}
29 Answers

Because "abstract" means: "Implements no functionality", and "static" means: "There is functionality even if you don't have an object instance". And that's a logical contradiction.

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.

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.

This is a terrible language design and really no reason as to why it can't be possible.

In fact, here is a pattern or way on how it can be mimicked in **Java ** to allow you at least be able to modify your own implementations:

public static abstract class Request {                 

        // Static method
        public static void doSomething() {
                get().doSomethingImpl();
        }
        
        // Abstract method
        abstract void doSomethingImpl();

        /////////////////////////////////////////////
        private static Request SINGLETON;
        private static Request get() {
            if ( SINGLETON == null ) {
                // If set(request) is never called prior,
                // it will use a default implementation. 
                return SINGLETON = new RequestImplementationDefault();
            }
            return SINGLETON;
        }
        public static Request set(Request instance){
            return SINGLETON = instance;
        }
        /////////////////////////////////////////////
}

Two implementations:

/////////////////////////////////////////////////////

public static final class RequestImplementationDefault extends Request {
        @Override void doSomethingImpl() {
                System.out.println("I am doing something AAA");
        }
}

/////////////////////////////////////////////////////

public static final class RequestImplementaionTest extends Request {
        @Override void doSomethingImpl() {
                System.out.println("I am doing something BBB");
        }
}

/////////////////////////////////////////////////////

Could be used as follows:

Request.set(new RequestImplementationDefault());

// Or

Request.set(new RequestImplementationTest());

// Later in the application you might use

Request.doSomething();

This would allow you to invoke your methods statically, yet be able to alter the implementation say for a Test environment.

Theoretically, you could do this on a ThreadLocal as well, and be able to set instance per Thread context instead rather than fully global as seen here, one would then be able to do Request.withRequest(anotherRequestImpl, () -> { ... }) or similar.

Real world usually do not require the ThreadLocal approach and usually it is enough to be able to alter implementation for Test environment globally.

Note, that the only purpose for this is to enable a way to retain the ability to invoke methods DIRECTLY, EASILY and CLEANLY which static methods provides while at the same time be able to switch implementation should a desire arise at the cost of slightly more complex implementation.

It is just a pattern to get around having normally non modifiable static code.

Declaring a method as static means we can call that method by its class name and if that class is abstract as well, it makes no sense to call it as it does not contain any body, and hence we cannot declare a method both as static and abstract.

As abstract methods belong to the class and cannot be overridden by the implementing class.Even if there is a static method with same signature , it hides the method ,does not override it. So it is immaterial to declare the abstract method as static as it will never get the body.Thus, compile time error.

A static method can be called without an instance of the class. In your example you can call foo.bar2(), but not foo.bar(), because for bar you need an instance. Following code would work:

foo var = new ImplementsFoo();
var.bar();

If you call a static method, it will be executed always the same code. In the above example, even if you redefine bar2 in ImplementsFoo, a call to var.bar2() would execute foo.bar2().

If bar2 now has no implementation (that's what abstract means), you can call a method without implementation. That's very harmful.

Because abstract class is an OOPS concept and static members are not the part of OOPS....
Now the thing is we can declare static complete methods in interface and we can execute interface by declaring main method inside an interface

interface Demo 
{
  public static void main(String [] args) {
     System.out.println("I am from interface");
  }
}

Because abstract mehods always need implementation by subclass.But if you make any method to static then overriding is not possible for this method

Example

abstract class foo {
    abstract static void bar2(); 
}


class Bar extends foo {
    //in this if you override foo class static method then it will give error
}

The idea of having an abstract static method would be that you can't use that particular abstract class directly for that method, but only the first derivative would be allowed to implement that static method (or for generics: the actual class of the generic you use).

That way, you could create for example a sortableObject abstract class or even interface with (auto-)abstract static methods, which defines the parameters of sort options:

public interface SortableObject {
    public [abstract] static String [] getSortableTypes();
    public String getSortableValueByType(String type);
}

Now you can define a sortable object that can be sorted by the main types which are the same for all these objects:

public class MyDataObject implements SortableObject {
    final static String [] SORT_TYPES = {
        "Name","Date of Birth"
    }
    static long newDataIndex = 0L ;

    String fullName ;
    String sortableDate ;
    long dataIndex = -1L ;
    public MyDataObject(String name, int year, int month, int day) {
        if(name == null || name.length() == 0) throw new IllegalArgumentException("Null/empty name not allowed.");
        if(!validateDate(year,month,day)) throw new IllegalArgumentException("Date parameters do not compose a legal date.");
        this.fullName = name ;
        this.sortableDate = MyUtils.createSortableDate(year,month,day);
        this.dataIndex = MyDataObject.newDataIndex++ ;
    }
    public String toString() {
        return ""+this.dataIndex+". "this.fullName+" ("+this.sortableDate+")";
    }

    // override SortableObject 
    public static String [] getSortableTypes() { return SORT_TYPES ; }
    public String getSortableValueByType(String type) {
        int index = MyUtils.getStringArrayIndex(SORT_TYPES, type);
        switch(index) {
             case 0: return this.name ;
             case 1: return this.sortableDate ;
        }
        return toString(); // in the order they were created when compared
    }
}

Now you can create a

public class SortableList<T extends SortableObject> 

that can retrieve the types, build a pop-up menu to select a type to sort on and resort the list by getting the data from that type, as well as hainv an add function that, when a sort type has been selected, can auto-sort new items in. Note that the instance of SortableList can directly access the static method of "T":

String [] MenuItems = T.getSortableTypes();

The problem with having to use an instance is that the SortableList may not have items yet, but already need to provide the preferred sorting.

Cheerio, Olaf.

There is one occurrence where static and abstract can be used together and that is when both of these modifiers are placed in front of a nested class.

Static Method A static method can be invoked without the need for creating an instance of a class.A static method belongs to the class rather than the object of a class. A static method can access static data member and also it can change the value of it. Abstract Keyword is used to implement abstraction. A static method can't be overriden or implemented in child class. So, there is no use of making static method as abstract.

In a single line, this dangerous combination (abstract + static) violates the object-oriented principle which is Polymorphism.

In an inheritance situation, the JVM will decide at runtime by the implementation in respect of the type of instance (runtime polymorphism) and not in respect of the type of reference variable (compile-time polymorphism).

With @Overriding:

enter image description here

Static methods do not support @overriding (runtime polymorphism), but only method hiding (compile-time polymorphism).

With @Hiding:

enter image description here

But in a situation of abstract static methods, the parent (abstract) class does not have implementation for the method. Hence, the child type reference is the only one available and it is not polymorphism.

Child reference is the only one available:

enter image description here

For this reason (suppress OOPs features), Java language considers abstract + static an illegal (dangerous) combination for methods.

Related