Why can't static methods be abstract in Java?

后端 未结 25 2186
不思量自难忘°
不思量自难忘° 2020-11-22 08:34

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
    ab         


        
相关标签:
25条回答
  • 2020-11-22 08:49

    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.

    0 讨论(0)
  • 2020-11-22 08:51

    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.

    0 讨论(0)
  • 2020-11-22 08:51

    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();
        }
    
    0 讨论(0)
  • 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.

    0 讨论(0)
  • 2020-11-22 08:54

    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.

    0 讨论(0)
  • 2020-11-22 08:54

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

    0 讨论(0)
提交回复
热议问题