问题是,在Java中为什么不能定义抽象静态方法?例如
abstract class foo {
abstract void bar( ); // <-- this is ok
abstract static void bar2(); //<-- this isn't why?
}
问题是,在Java中为什么不能定义抽象静态方法?例如
abstract class foo {
abstract void bar( ); // <-- this is ok
abstract static void bar2(); //<-- this isn't why?
}
当前回答
我也问了同样的问题,原因如下
因为抽象类说,它不会给出实现,并允许子类给出它
所以子类必须重写超类的方法,
规则1 -静态方法不能被覆盖
因为静态成员和方法是编译时元素,这就是为什么允许重载(编译时多态性)静态方法而不是重写(运行时多态性)
所以它们不可能是抽象的。
Java宇宙中不允许有抽象静态<——之类的东西
其他回答
假设有两个类,父类和子类。父母是抽象的。声明如下:
abstract class Parent {
abstract void run();
}
class Child extends Parent {
void run() {}
}
这意味着Parent的任何实例都必须指定如何执行run()。
但是,现在假设Parent不是抽象的。
class Parent {
static void run() {}
}
这意味着Parent.run()将执行静态方法。
抽象方法的定义是“声明但未实现的方法”,这意味着它本身不返回任何东西。
静态方法的定义是“对于相同的参数返回相同值的方法,而不管调用它的实例是什么”。
抽象方法的返回值会随着实例的改变而改变。静态方法则不会。静态抽象方法基本上是这样一种方法,它的返回值是常量,但不返回任何东西。这是一个逻辑矛盾。
同样,使用静态抽象方法的理由也不多。
你不能重写静态方法,所以使它抽象是没有意义的。此外,抽象类中的静态方法将属于该类,而不是覆盖类,因此无论如何都不能使用。
因为abstract是应用于abstract方法上的关键字,所以abstract方法不指定主体。而静态关键字则属于类区域。
静态方法 可以调用静态方法,而不需要创建类的实例。静态方法属于类,而不是类的对象。 静态方法可以访问静态数据成员,也可以改变它的值。 摘要关键字用于实现抽象。 静态方法不能在子类中重写或实现。因此,把静态方法做得抽象是没有用的。
这是一个糟糕的语言设计,真的没有理由不可能。
事实上,这里有一个模式或方法可以在**Java中模仿它,让你至少能够修改自己的实现:
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;
}
/////////////////////////////////////////////
}
两种实现:
/////////////////////////////////////////////////////
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");
}
}
/////////////////////////////////////////////////////
可以这样使用:
Request.set(new RequestImplementationDefault());
// Or
Request.set(new RequestImplementationTest());
// Later in the application you might use
Request.doSomething();
这将允许您静态地调用方法,同时还能够更改例如Test环境的实现。
理论上,您也可以在ThreadLocal上执行此操作,并且能够为每个线程上下文设置实例,而不是像这里所示的完全全局,然后可以执行Request。withRequest(anotherRequestImpl,() ->{…})或类似的。
现实世界通常不需要ThreadLocal方法,通常能够全局地改变测试环境的实现就足够了。
请注意,这样做的唯一目的是能够保留静态方法所提供的直接、轻松和干净地调用方法的能力,同时能够切换实现,以牺牲稍微复杂的实现为代价。
它只是一种绕过通常不可修改的静态代码的模式。