问题是在Java中为什么我不能定义一个抽象的静态方法?例如
abstract class foo { abstract void bar( ); // <-- this is ok abstract static void bar2(); //<-- this isn't why? }
Tomalak.. 544
因为"abstract"意味着:"实现没有功能","静态"意味着:"即使你没有对象实例也有功能".这是一个合乎逻辑的矛盾.
因为"abstract"意味着:"实现没有功能","静态"意味着:"即使你没有对象实例也有功能".这是一个合乎逻辑的矛盾.
语言设计不佳.直接调用静态抽象方法比仅使用该抽象方法创建实例会更有效.当使用抽象类作为枚举无法扩展的变通方法时尤其如此,这是另一个糟糕的设计示例.希望他们在下一个版本中解决这些限制.
您不能覆盖静态方法,因此将其抽象化将毫无意义.此外,在抽象类的静态方法将属于这个阶层,而不是覆盖类,因此无法使用反正.
abstract
方法的注释表明该方法必须在子类中重写.
在Java中,static
子类不能覆盖成员(方法或字段)(在其他面向对象的语言中不一定如此,请参阅SmallTalk.)static
成员可能被隐藏,但这与被覆盖的根本不同.
由于静态成员无法在子类中重写,abstract
因此无法将注释应用于它们.
另外 - 其他语言确实支持静态继承,就像实例继承一样.从语法的角度来看,这些语言通常需要将类名包含在语句中.例如,在Java中,假设您在ClassA中编写代码,这些是等效语句(如果methodA()是静态方法,并且没有具有相同签名的实例方法):
ClassA.methodA();
和
methodA();
在SmallTalk中,类名不是可选的,因此语法是(请注意,SmallTalk不使用.来分隔"主题"和"动词",而是将其用作statemend终结符):
ClassA methodA.
由于始终需要类名,因此始终可以通过遍历类层次结构来确定方法的正确"版本".对于它的价值,我偶尔会错过static
继承,并且当我第一次开始使用Java时,由于缺乏静态继承而被咬了.另外,SmallTalk是鸭子类型(因此不支持逐个程序.)因此,它没有abstract
类成员的修饰符.
我也问了同样的问题,这就是原因
从Abstract类开始说,它不会给出实现并允许子类给它
所以Subclass必须覆盖Superclass的方法,
RULE NO 1 - 无法覆盖静态方法
因为静态成员和方法是编译时元素,这就是为什么允许静态方法的重载(编译时多态)而不是覆盖(运行时多态)
所以,他们不能抽象.
没有抽象静态 <--- Java Universe中不允许的东西
这是一个糟糕的语言设计,并没有理由为什么它不可能.
事实上,这里是如何实现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; } } }
=================下面的旧例子=================
查找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(); } } }
仅定义抽象方法,以便可以在子类中重写它.但是,无法覆盖静态方法.因此,具有抽象的静态方法是编译时错误.
现在接下来的问题是为什么静态方法不能被覆盖?
这是因为静态方法属于特定类而不属于其实例.如果您尝试覆盖静态方法,则不会得到任何编译或运行时错误,但编译器只会隐藏超类的静态方法.