Home » Java » Why can't static methods be abstract in Java

Why can't static methods be abstract in Java

Posted by: admin November 2, 2017 Leave a comment

Questions:

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?
}
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.

Questions:
Answers:

Poor language design. It would be much more effective to call directly a static abstract method than creating an instance just for using that abstract method. Especially true when using an abstract class as a workaround for enum inability to extend, which is another poor design example. Hope they solve those limitations in a next release.

Questions:
Answers:

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.

Questions:
Answers:

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.

Questions:
Answers:

I also asked the same question , here is why

Since Abstract class says, it will not give implementation and allow subclass to give it

so Subclass has to override the methods of Superclass ,

RULE NO 1A static method cannot be overridden

Because static members and methods are compile time elements , that is why Overloading(Compile time Polymorphism) of static methods are allowed rather then Overriding (Runtime Polymorphism)

So , they cant be Abstract .

There is no thing like abstract static <— Not allowed in Java Universe

Questions:
Answers:

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

In fact, here is an implementation on how it CAN be done in JAVA:

public class Main {

        public static void main(String[] args) {
                // This is done once in your application, usually at startup
                Request.setRequest(new RequestImplementationOther());

                Request.doSomething();
        }

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

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

        // Static methods in here can be overriden
        public static abstract class Request {

                abstract void doSomethingImpl();

                // Static method
                public static void doSomething() {
                        getRequest().doSomethingImpl();
                }

                private static Request request;
                private static Request getRequest() {
                        // If setRequest is never called prior, it will default to a default implementation. Of course you could ignore that too. 
                        if ( request == null ) {
                                return request = new RequestImplementationDefault();
                        }
                        return request;
                }
                public static Request setRequest(Request r){
                        return request = r;
                }

        }
}

================= Old example below =================

Look for getRequest, and getRequestImpl … setInstance can be called to alter the implementation before the call is made.

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

/**
 * @author Mo. Joseph
 * @date 16 mar 2012
 **/

public abstract class Core {


    // ---------------------------------------------------------------        
    private static Core singleton; 
    private static Core getInstance() {
        if ( singleton == null )
            setInstance( new Core.CoreDefaultImpl() );  // See bottom for CoreDefaultImpl

        return singleton;
    }    

    public static void setInstance(Core core) {
        Core.singleton = core;
    }
    // ---------------------------------------------------------------        



    // Static public method
    public static HttpServletRequest getRequest() {      
        return getInstance().getRequestImpl();
    }


    // A new implementation would override this one and call setInstance above with that implementation instance
    protected abstract HttpServletRequest getRequestImpl();




    // ============================ CLASSES =================================

    // ======================================================================
    // == Two example implementations, to alter getRequest() call behaviour 
    // == getInstance() have to be called in all static methods for this to work
    // == static method getRequest is altered through implementation of getRequestImpl
    // ======================================================================

    /** Static inner class CoreDefaultImpl */
    public static class CoreDefaultImpl extends Core { 
        protected HttpServletRequest getRequestImpl() {
            return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        }
    }

     /** Static inner class CoreTestImpl : Alternative implementation */
    public static class CoreTestImpl extends Core { 
        protected HttpServletRequest getRequestImpl() {
            return new MockedRequest();
        }
    }       






}

Questions:
Answers:
  • An abstract method is defined only so that it can be overridden in a subclass. However, static methods can not be overridden. Therefore, it is a compile-time error to have an abstract, static method.

    Now the next question is why static methods can not be overridden??

  • It’s because static methods belongs to a particular class and not to its instance. If you try to override a static method you will not get any compilation or runtime error but compiler would just hide the static method of superclass.

Questions:
Answers:

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

Questions:
Answers:

Assume there are two classes, Parent and Child. Parent is abstract. The declarations are as follows:

abstract class Parent {
    abstract void run();
}

class Child extends Parent {
    void run() {}
}

This means that any instance of Parent must specify how run() is executed.

However, assume now that Parent is not abstract.

class Parent {
    static void run() {}
}

This means that Parent.run() will execute the static method.

The definition of an abstract method is “A method that is declared but not implemented”, which means it doesn’t return anything itself.

The definition of a static method is “A method that returns the same value for the same parameters regardless of the instance on which it is called”.

An abstract method’s return value will change as the instance changes. A static method will not. A static abstract method is pretty much a method where the return value is constant, but does not return anything. This is a logical contradiction.

Also, there is really not much of a reason for a static abstract method.

Questions:
Answers:

An abstract class cannot have a static method because abstraction is done to achieve DYNAMIC BINDING while static methods are statically binded to their functionality.A static method means
behavior not dependent on an instance variable, so no instance/object
is required.Just the class.Static methods belongs to class and not object.
They are stored in a memory area known as PERMGEN from where it is shared with every object.
Methods in abstract class are dynamically binded to their functionality.

Questions:
Answers:

I see that there are a god-zillion answers already but I don’t see any practical solutions. Of course this is a real problem and there is no good reason for excluding this syntax in Java. Since the original question lacks a context where this may be need, I provide both a context and a solution:

Suppose you have a static method in a bunch of classes that are identical. These methods call a static method that is class specific:

class C1 {
    static void doWork() {
        ...
        for (int k: list)
            doMoreWork(k);
        ...
    }
    private static void doMoreWork(int k) {
        // code specific to class C1
    }
}
class C2 {
    static void doWork() {
        ...
        for (int k: list)
            doMoreWork(k);
        ...
    }
    private static void doMoreWork(int k) {
        // code specific to class C2
    }
}

doWork() methods in C1 and C2 are identical. There may be a lot of these calsses: C3 C4 etc. If static abstract was allowed, you’d eliminate the duplicate code by doing something like:

abstract class C {
    static void doWork() {
        ...
        for (int k: list)
            doMoreWork(k);
        ...
    }

    static abstract void doMoreWork(int k);
}

class C1 extends C {
    private static void doMoreWork(int k) {
        // code for class C1
    }
}

class C2 extends C {
    private static void doMoreWork(int k) {
        // code for class C2
    }
}

but this would not compile because static abstract combination is not allowed.
However, this can be circumvented with static class construct, which is allowed:

abstract class C {
    void doWork() {
        ...
        for (int k: list)
            doMoreWork(k);
        ...
    }
    abstract void doMoreWork(int k);
}
class C1 {
    private static final C c = new  C(){  
        @Override void doMoreWork(int k) {
            System.out.println("code for C1");
        }
    };
    public static void doWork() {
        c.doWork();
    }
}
class C2 {
    private static final C c = new C() {
        @Override void doMoreWork(int k) {
            System.out.println("code for C2");
        }
    };
    public static void doWork() {
        c.doWork();
    }
}

With this solution the only code that is duplicated is

    public static void doWork() {
        c.doWork();
    }

Questions:
Answers:

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.

Questions:
Answers:

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).

Questions:
Answers:

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

Questions:
Answers:

A static method, by definition, doesn’t need to know this. Thus, it cannot be a virtual method (that is overloaded according to dynamic subclass information available through this); instead, a static method overload is solely based on info available at compile time (this means: once you refer a static method of superclass, you call namely the superclass method, but never a subclass method).

According to this, abstract static methods would be quite useless because you will never have its reference substituted by some defined body.

Questions:
Answers:

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.

Questions:
Answers:

First, a key point about abstract classes –
An abstract class cannot be instantiated (see wiki). So, you can’t create any instance of an abstract class.

Now, the way java deals with static methods is by sharing the method with all the instances of that class.

So, If you can’t instantiate a class, that class can’t have abstract static methods since an abstract method begs to be extended.

Boom.

Questions:
Answers:

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));
    }    
}

Questions:
Answers:

Regular methods can be abstract when they are meant to be overridden by subclasses and provided with functionality.
Imagine the class Foo is extended by Bar1, Bar2, Bar3 etc. So, each will have their own version of the abstract class according to their needs.

Now, static methods by definition belong to the class, they have nothing to do with the objects of the class or the objects of its subclasses. They don’t even need them to exist, they can be used without instantiating the classes. Hence, they need to be ready-to-go and cannot depend on the subclasses to add functionality to them.

Questions:
Answers:

Because abstract is a keyword which is applied over Abstract methods do not specify a body. And If we talk about static keyword it belongs to class area.

Questions:
Answers:

Because if a class extends an abstract class then it has to override abstract methods and that is mandatory. And since static methods are class methods resolved at compile time whereas overridden methods are instance methods resolved at runtime and following dynamic polymorphism.