简单的回答是:这是完全有可能的,但Java并没有做到这一点。
下面是一些代码,它说明了现状在Java中:
档案Base.java:package sp.trial;public class Base {
static void printValue() {
System.out.println(" Called static Base method.");
}
void nonStatPrintValue() {
System.out.println(" Called non-static Base method.");
}
void nonLocalIndirectStatMethod() {
System.out.println(" Non-static calls overridden(?) static:");
System.out.print(" ");
this.printValue();
}}
档案Child.java:package sp.trial;public class Child extends Base {
static void printValue() {
System.out.println(" Called static Child method.");
}
void nonStatPrintValue() {
System.out.println(" Called non-static Child method.");
}
void localIndirectStatMethod() {
System.out.println(" Non-static calls own static:");
System.out.print(" ");
printValue();
}
public static void main(String[] args) {
System.out.println("Object: static type Base; runtime type Child:");
Base base = new Child();
base.printValue();
base.nonStatPrintValue();
System.out.println("Object: static type Child; runtime type Child:");
Child child = new Child();
child.printValue();
child.nonStatPrintValue();
System.out.println("Class: Child static call:");
Child.printValue();
System.out.println("Class: Base static call:");
Base.printValue();
System.out.println("Object: static/runtime type Child -- call static from non-static method of Child:");
child.localIndirectStatMethod();
System.out.println("Object: static/runtime type Child -- call static from non-static method of Base:");
child.nonLocalIndirectStatMethod();
}}
如果您使用Java 1.6运行此操作(我是在Eclipse中的Mac上运行的,使用Java 1.6),您将得到以下结果:Object: static type Base; runtime type Child.
Called static Base method.
Called non-static Child method.Object: static type Child; runtime type Child.
Called static Child method.
Called non-static Child method.Class: Child static call.
Called static Child method.Class: Base static call.
Called static Base method.Object: static/runtime type Child -- call static from non-static method of Child.
Non-static calls own static.
Called static Child method.Object: static/runtime type Child -- call static from non-static method of Base.
Non-static calls overridden(?) static.
Called static Base method.
在这里,只可能令人惊讶的案件(以及问题所在)似乎是第一案件:
“即使在使用对象实例调用时,运行时类型也不用于确定调用哪些静态方法(obj.staticMethod())."
而最活的,刚过去的案件:
“当从类的对象方法中调用静态方法时,所选择的静态方法是从类本身和不定义对象的运行时类型的类。“
用对象实例调用
静态调用在编译时解析,而非静态方法调用在运行时解析.注意,虽然静态方法是继承(来自父母)他们不是重写(按儿童计算)。如果你不这么想的话,这可能是个惊喜。
从对象方法中调用
对象方法调用使用运行时类型进行解析,但是静态的(班级,等级)使用编译时(声明)类型解析方法调用。
改变规则
更改这些规则,以便示例中的最后一个调用称为Child.printValue(),静态调用必须在运行时提供类型,而不是编译器在编译时使用对象(或上下文)的声明类解析调用。然后,静态调用可以使用(动态)类型层次结构来解析调用,就像对象方法调用现在所做的那样。
这很容易做到(如果我们更改了Java:-O),而且一点也不合理,但是,它有一些有趣的考虑。
主要考虑是我们需要决定哪一个静态方法调用应该这样做。
目前,Java在语言中有一个“怪癖”obj.staticMethod()调用被替换为ObjectClass.staticMethod()呼叫(通常带有警告)。[注: ObjectClass的编译时类型。obj.]这些是以这种方式重写的很好的候选程序,采用运行时类型的obj.
如果这样做,将使方法主体更难阅读:父类中的静态调用可能是动态“改道”为了避免这种情况,我们必须使用类名调用静态方法-这使得使用编译时类型层次结构(与现在一样)更明显地解决了调用。
调用静态方法的其他方法更棘手:this.staticMethod()应该意味着和obj.staticMethod()的运行时类型this..然而,这可能会给现有程序带来一些麻烦,这些程序调用(显然是本地的)静态方法而不进行修饰(这可以说相当于this.method()).
那么没有装饰的电话呢?staticMethod()?我建议他们和今天做同样的事情,并使用本地类上下文来决定该做什么。否则会引起极大的混乱。当然这意味着method()就意味着this.method()如果method是一种非静态的方法,而且ThisClass.method()如果method是一种静态的方法。这是另一个混乱的根源。
其他考虑
如果我们改变了这种行为(并进行了潜在的动态非本地的静态调用),我们可能希望重新讨论final, private和protected作为限定符static课堂方法。这样我们就得习惯这样一个事实private static和public final方法不会被重写,因此可以在编译时安全地解析,并且作为本地引用读取是“安全的”。