为什么Java中的静态方法不能是抽象的

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/370962/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 13:56:55  来源:igfitidea点击:

Why can't static methods be abstract in Java

javaabstract-classstatic-methods

提问by hhafez

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

问题是在 Java 中为什么我不能定义抽象静态方法?例如

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

回答by GaryF

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.

您不能覆盖静态方法,因此将其抽象化将毫无意义。此外,抽象类中的静态方法属于该类,而不是覆盖类,因此无论如何都不能使用。

回答by Tomalak

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.

因为“抽象”的意思是:“不实现功能”,而“静态”的意思是:“即使没有对象实例也有功能”。这是一个逻辑上的矛盾。

回答by Mnementh

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.bar2(),但不能调用 foo.bar(),因为对于 bar,您需要一个实例。以下代码将起作用:

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

如果您调用静态方法,它将始终执行相同的代码。在上面的例子中,即使你在ImplementsFoo 中重新定义了bar2,对var.bar2() 的调用也会执行foo.bar2()。

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

如果 bar2 现在没有实现(这就是抽象的意思),你可以调用一个没有实现的方法。这是非常有害的。

回答by Jared

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

abstract方法的注释表明该方法必须在子类中被覆盖。

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

在 Java 中,static成员(方法或字段)不能被子类覆盖(在其他面向对象的语言中不一定如此,请参阅 SmallTalk。)static成员可能是隐藏的,但这与覆盖有根本的不同。

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

由于静态成员不能在子类中被覆盖,因此abstract注释不能应用于它们。

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

顺便说一句 - 其他语言确实支持静态继承,就像实例继承一样。从语法的角度来看,这些语言通常要求在语句中包含类名。例如,在 Java 中,假设您在 ClassA 中编写代码,这些是等效语句(如果 methodA() 是静态方法,并且没有具有相同签名的实例方法):

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

在 SmallTalk 中,类名不是可选的,所以语法是(注意 SmallTalk 不使用 . 分隔“主语”和“动词”,而是使用它作为语句终止符):

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 staticinheritance, 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 abstractmodifier for class members.

由于始终需要类名,因此始终可以通过遍历类层次结构来确定方法的正确“版本”。对于它的价值,我偶尔会错过static继承,并且在我第一次开始使用 Java 时被 Java 中缺少静态继承所困扰。此外,SmallTalk 是鸭子类型的(因此不支持按合同编程。)因此,它没有abstract用于类成员的修饰符。

回答by Jared

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.

糟糕的语言设计。直接调用静态抽象方法比仅仅为了使用该抽象方法而创建实例要有效得多。当使用抽象类作为枚举无法扩展的解决方法时尤其如此,这是另一个糟糕的设计示例。希望他们在下一个版本中解决这些限制。

回答by mmm

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 CANbe done in JAVA:

事实上,这里是如何实现CAN在做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.

查找 getRequest 和 getRequestImpl ... setInstance 可以在调用之前调用以更改实现。

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

}

Used as follow:

用法如下:

static {
     Core.setSingleton(new Core.CoreDefaultImpl());

     // Or

     Core.setSingleton(new Core.CoreTestImpl());

     // Later in the application you might use

     Core.getRequest(); 

}

回答by Rahul Saxena

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

  • 定义抽象方法只是为了可以在子类中覆盖它。但是,不能覆盖静态方法。因此,拥有抽象的静态方法是编译时错误。

    现在下一个问题是为什么不能覆盖静态方法?

  • 这是因为静态方法属于一个特定的类而不是它的实例。如果您尝试覆盖静态方法,则不会出现任何编译或运行时错误,但编译器只会隐藏超类的静态方法。

回答by Anubhav Nigam

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.

因为如果一个类扩展了一个抽象类,那么它必须覆盖抽象方法,这是强制性的。并且由于静态方法是在编译时解析的类方法,而覆盖方法是在运行时解析并遵循动态多态性的实例方法。

回答by anshulkatta

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 ,

所以 Subclass 必须覆盖 Superclass 的方法,

RULE NO 1- A static method cannot be overridden

规则 1-静态方法不能被覆盖

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

没有像abstract static<--- Java Universe 中不允许的东西

回答by Olaf Leimann

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:

这样,您可以创建例如 sortableObject 抽象类,甚至与(自动)抽象静态方法的接口,它定义了排序选项的参数:

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":

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。注意SortableList的实例可以直接访问“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.

必须使用实例的问题是 SortableList 可能还没有项目,但已经需要提供首选排序。

Cheerio, Olaf.

啦啦啦,奥拉夫。