为什么 Java 不允许覆盖静态方法?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2223386/
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-13 04:53:54  来源:igfitidea点击:

Why doesn't Java allow overriding of static methods?

javastaticoverridingstatic-methods

提问by sgokhales

Why is it not possible to override static methods?

为什么不能覆盖静态方法?

If possible, please use an example.

如果可能,请举例说明。

采纳答案by Nathan Hughes

Overriding depends on having an instance of a class. The point of polymorphism is that you can subclass a class and the objects implementing those subclasses will have different behaviors for the same methods defined in the superclass (and overridden in the subclasses). A static method is not associated with any instance of a class so the concept is not applicable.

覆盖取决于拥有一个类的实例。多态性的要点是您可以对一个类进行子类化,并且实现这些子类的对象对于在超类中定义的相同方法(并在子类中被覆盖)将具有不同的行为。静态方法不与类的任何实例相关联,因此该概念不适用。

There were two considerations driving Java's design that impacted this. One was a concern with performance: there had been a lot of criticism of Smalltalk about it being too slow (garbage collection and polymorphic calls being part of that) and Java's creators were determined to avoid that. Another was the decision that the target audience for Java was C++ developers. Making static methods work the way they do had the benefit of familiarity for C++ programmers and was also very fast, because there's no need to wait until runtime to figure out which method to call.

推动 Java 设计的有两个考虑因素影响了这一点。一个是对性能的关注:有很多批评 Smalltalk 说它太慢(垃圾收集和多态调用是其中的一部分),而 Java 的创建者决心避免这种情况。另一个是 Java 的目标受众是 C++ 开发人员的决定。使静态方法按照它们的方式工作对 C++ 程序员来说很熟悉,而且速度也非常快,因为不需要等到运行时才确定要调用哪个方法。

回答by ewernli

Static methods are treated as global by the JVM, there are not bound to an object instance at all.

JVM 将静态方法视为全局方法,根本没有绑定到对象实例。

It could conceptually be possible if you could call static methods from class objects (like in languages like Smalltalk) but it's not the case in Java.

如果您可以从类对象调用静态方法(例如在 Smalltalk 之类的语言中),那么从概念上讲这是可能的,但在 Java 中则不然。

EDIT

编辑

You can overloadstatic method, that's ok. But you can not overridea static method, because class are no first-class object. You can use reflection to get the class of an object at run-time, but the object that you get does not parallel the class hierarchy.

你可以重载静态方法,没关系。但是您不能覆盖静态方法,因为类不是一流的对象。您可以使用反射在运行时获取对象的类,但您获取的对象与类层次结构并不平行。

class MyClass { ... }
class MySubClass extends MyClass { ... }

MyClass obj1 = new MyClass();
MySubClass obj2 = new MySubClass();

ob2 instanceof MyClass --> true

Class clazz1 = obj1.getClass();
Class clazz2 = obj2.getClass();

clazz2 instanceof clazz1 --> false

You can reflect over the classes, but it stops there. You don't invoke a static method by using clazz1.staticMethod(), but using MyClass.staticMethod(). A static method is not bound to an object and there is hence no notion of thisnor superin a static method. A static method is a global function; as a consequence there is also no notion of polymorphism and, therefore, method overriding makes no sense.

你可以反思课程,但它停在那里。您不是通过 using 调用静态方法clazz1.staticMethod(),而是使用MyClass.staticMethod(). 静态方法没有绑定到一个对象,并有因此没有的概念this,也没有super在一个静态方法。静态方法是一个全局函数;因此,也没有多态的概念,因此,方法覆盖没有意义。

But this could be possible if MyClasswas an object at run-time on which you invoke a method, as in Smalltalk (or maybe JRuby as one comment suggest, but I know nothing of JRuby).

但是,如果MyClass是在运行时调用方法的对象,这可能是可能的,就像在 Smalltalk 中一样(或者可能是 JRuby,正如一个评论所暗示的那样,但我对 JRuby 一无所知)。

Oh yeah... one more thing. You can invoke a static method through an object obj1.staticMethod()but that really syntactic sugar for MyClass.staticMethod()and should be avoided. It usually raises a warning in modern IDE. I don't know why they ever allowed this shortcut.

哦,是的……还有一件事。您可以通过对象调用静态方法,obj1.staticMethod()MyClass.staticMethod()应该避免使用真正的语法糖。它通常会在现代 IDE 中引发警告。我不知道他们为什么允许这条捷径。

回答by Athens Holloway

overriding is reserved for instance members to support polymorphic behaviour. static class members do not belong to a particular instance. instead, static members belong to the class and as a result overriding is not supported because subclasses only inherit protected and public instance members and not static members. You may want to define an inerface and research factory and/or strategy design patterns to evaluate an alternate approach.

覆盖是为实例成员保留的,以支持多态行为。静态类成员不属于特定实例。相反,静态成员属于类,因此不支持覆盖,因为子类只继承受保护和公共实例成员,而不是静态成员。您可能想要定义一个接口和研究工厂和/或策略设计模式来评估替代方法。

回答by fastcodejava

What good will it do to override static methods. You cannot call static methods through an instance.

覆盖静态方法有什么好处。您不能通过实例调用静态方法。

MyClass.static1()
MySubClass.static1()   // If you overrode, you have to call it through MySubClass anyway.

EDIT : It appears that through an unfortunate oversight in language design, you cancall static methods through an instance. Generally nobody does that. My bad.

编辑:似乎通过语言设计中的一个不幸疏忽,您可以通过实例调用静态方法。一般没有人这样做。我的错。

回答by Jay

Personally I think this is a flaw in the design of Java. Yes, yes, I understand that non-static methods are attached to an instance while static methods are attached to a class, etc etc. Still, consider the following code:

我个人认为这是Java设计的一个缺陷。是的,是的,我知道非静态方法附加到实例,而静态方法附加到类等。不过,请考虑以下代码:

public class RegularEmployee {
    private BigDecimal salary;

    public void setSalary(BigDecimal salary) {
        this.salary = salary;
    }

    public static BigDecimal getBonusMultiplier() {
        return new BigDecimal(".02");
    }

    public BigDecimal calculateBonus() {
        return salary.multiply(getBonusMultiplier());
    }

    /* ... presumably lots of other code ... */
}

public class SpecialEmployee extends RegularEmployee {
    public static BigDecimal getBonusMultiplier() {
        return new BigDecimal(".03");
    }
}

This code will not work as you might expect. Namely, SpecialEmployee's get a 2% bonus just like regular employees. But if you remove the "static"s, then SpecialEmployee's get a 3% bonus.

此代码不会像您预期的那样工作。也就是说,SpecialEmployee 像普通员工一样获得 2% 的奖金。但是,如果您删除“静态”,那么 SpecialEmployee 将获得 3% 的奖金。

(Admittedly, this example is poor coding style in that in real life you would likely want the bonus multiplier to be in a database somewhere rather than hard-coded. But that's just because I didn't want to bog down the example with a lot of code irrelevant to the point.)

(诚​​然,这个例子是糟糕的编码风格,因为在现实生活中你可能希望奖金乘数在某个数据库中而不是硬编码。但这只是因为我不想让这个例子陷入困境与要点无关的代码。)

It seems quite plausible to me that you might want to make getBonusMultiplier static. Perhaps you want to be able to display the bonus multiplier for all the categories of employees, without needing to have an instance of an employee in each category. What would be the point of searching for such example instances? What if we are creating a new category of employee and don't have any employees assigned to it yet? This is quite logically a static function.

对我来说,您可能希望将 getBonusMultiplier 设为静态似乎很合理。也许您希望能够为所有类别的员工显示奖金乘数,而无需在每个类别中都有一个员工的实例。搜索此类示例实例有什么意义?如果我们正在创建一个新的员工类别并且还没有任何员工分配给它怎么办?这在逻辑上是一个静态函数。

But it doesn't work.

但它不起作用。

And yes, yes, I can think of any number of ways to rewrite the above code to make it work. My point is not that it creates an unsolvable problem, but that it creates a trap for the unwary programmer, because the language does not behave as I think a reasonable person would expect.

是的,是的,我可以想出许多方法来重写上述代码以使其工作。我的观点不是它造成了一个无法解决的问题,而是它为粗心的程序员制造了一个陷阱,因为该语言的行为并不像我认为一个理性的人所期望的那样。

Perhaps if I tried to write a compiler for an OOP language, I would quickly see why implementing it so that static functions can be overriden would be difficult or impossible.

也许如果我尝试为 OOP 语言编写编译器,我会很快明白为什么实现它以便可以覆盖静态函数是困难或不可能的。

Or perhaps there is some good reason why Java behaves this way. Can anyone point out an advantage to this behavior, some category of problem that is made easier by this? I mean, don't just point me to the Java language spec and say "see, this is documented how it behaves". I know that. But is there a good reason why it SHOULD behave this way? (Besides the obvious "making it work right was too hard"...)

或者也许有一些很好的理由为什么 Java 会这样。任何人都可以指出这种行为的优势,某些类别的问题因此变得更容易?我的意思是,不要只是将我指向 Java 语言规范并说“看,这是记录了它的行为方式”。我知道。但是,它应该这样做是否有充分的理由?(除了明显的“让它正常工作太难了”......)

Update

更新

@VicKirk: If you mean that this is "bad design" because it doesn't fit how Java handles statics, my reply is, "Well, duh, of course." As I said in my original post, it doesn't work. But if you mean that it is bad design in the sense that there would be something fundamentally wrong with a language where this worked, i.e. where statics could be overridden just like virtual functions, that this would somehow introduce an ambiguity or it would be impossible to implement efficiently or some such, I reply, "Why? What's wrong with the concept?"

@VicKirk:如果你的意思是这是“糟糕的设计”,因为它不适合 Java 处理静态的方式,我的回答是,“好吧,当然是废话。” 正如我在原帖中所说,它不起作用。但是,如果您的意思是说这是一种糟糕的设计,因为在这种情况下,这种工作的语言会存在根本性的错误,即静态可以像虚函数一样被覆盖,那么这会以某种方式引入歧义,或者不可能有效地实施或类似的,我回答说,“为什么?这个概念有什么问题?”

I think the example I give is a very natural thing to want to do. I have a class that has a function that does not depend on any instance data, and which I might very reasonably want to call independent of an instance, as well as wanting to call from within an instance method. Why should this not work? I've run into this situation a fair number of times over the years. In practice I get around it by making the function virtual, and then creating a static method whose only purpose in life is to be a static method that passes the call on to the virtual method with a dummy instance. That seems like a very roundabout way to get there.

我认为我给出的例子是很自然的事情。我有一个类,它有一个不依赖于任何实例数据的函数,我可能非常想独立于实例调用它,以及想从实例方法中调用它。为什么这不起作用?这些年来,我遇到过很多次这种情况。在实践中,我通过将函数设为虚拟来解决这个问题,然后创建一个静态方法,它在生活中的唯一目的是成为一个静态方法,通过一个虚拟实例将调用传递给虚拟方法。这似乎是到达那里的一种非常迂回的方式。

回答by Lars

In general it doesn't make sense to allow 'overriding' of static methods as there would be no good way to determine which one to call at runtime. Taking the Employee example, if we call RegularEmployee.getBonusMultiplier() - which method is supposed to be executed?

一般来说,允许“覆盖”静态方法是没有意义的,因为没有好的方法可以确定在运行时调用哪个方法。以 Employee 为例,如果我们调用 RegularEmployee.getBonusMultiplier() - 应该执行哪个方法?

In the case of Java, one could imagine a language definition where it is possible to 'override' static methods as long as they are called through an object instance. However, all this would do is to re-implement regular class methods, adding redundancy to the language without really adding any benefit.

在 Java 的情况下,人们可以想象一种语言定义,只要它们通过对象实例调用,就可以“覆盖”静态方法。然而,所有这些都只是重新实现常规的类方法,为语言添加冗余,而没有真正增加任何好处。

回答by Kevin Brock

In Java (and many OOP languages, but I cannot speak for all; and some do not have static at all) all methods have a fixed signature - the parameters and types. In a virtual method, the first parameter is implied: a reference to the object itself and when called from within the object, the compiler automatically adds this.

在 Java(和许多 OOP 语言,但我不能代表所有语言;有些方法根本没有静态)中,所有方法都有一个固定的签名 - 参数和类型。在虚方法中,第一个参数是隐含的:对对象本身的引用,当从对象内部调用时,编译器会自动添加this.

There is no difference for static methods - they still have a fixed signature. However, by declaring the method static you have explicitly stated that the compiler must not include the implied object parameter at the beginning of that signature. Therefore, any other code that calls this must must not attempt to put a reference to an object on the stack. If it did do that, then the method execution would not work since the parameters would be in the wrong place - shifted by one - on the stack.

静态方法没有区别——它们仍然有一个固定的签名。但是,通过将方法声明为静态,您已明确声明编译器不得在该签名的开头包含隐含的对象参数。因此,调用 this 的任何其他代码不得尝试将对象的引用放在堆栈上。如果确实这样做了,那么方法执行将不起作用,因为参数将位于错误的位置 - 移动了一个 - 在堆栈上。

Because of this difference between the two; virtual methods always have a reference to the context object (i.e. this) so then it is possible to reference anything within the heap that belong to that instance of the object. But with static methods, since there is no reference passed, that method cannot access any object variables and methods since the context is not known.

由于两者之间的这种差异;虚拟方法总是引用上下文对象(即this),因此可以引用堆中属于该对象实例的任何内容。但是对于静态方法,由于没有传递引用,该方法无法访问任何对象变量和方法,因为上下文未知。

If you wish that Java would change the definition so that a object context is passed in for every method, static or virtual, then you would in essence have only virtual methods.

如果您希望 Java 更改定义,以便为每个方法(静态或虚拟)传入对象上下文,那么您本质上将只有虚拟方法。

As someone asked in a comment to the op - what is your reason and purpose for wanting this feature?

正如有人在对 op 的评论中所问的那样 - 您想要此功能的原因和目的是什么?

I do not know Ruby much, as this was mentioned by the OP, I did some research. I see that in Ruby classes are really a special kind of object and one can create (even dynamically) new methods. Classes are full class objects in Ruby, they are not in Java. This is just something you will have to accept when working with Java (or C#). These are not dynamic languages, though C# is adding some forms of dynamic. In reality, Ruby does not have "static" methods as far as I could find - in that case these are methods on the singleton class object. You can then override this singleton with a new class and the methods in the previous class object will call those defined in the new class (correct?). So if you called a method in the context of the original class it still would only execute the original statics, but calling a method in the derived class, would call methods either from the parent or sub-class. Interesting and I can see some value in that. It takes a different thought pattern.

我不太了解Ruby,因为OP提到了这一点,我做了一些研究。我看到在 Ruby 中类确实是一种特殊的对象,可以创建(甚至是动态的)新方法。类是 Ruby 中的完整类对象,它们不是 Java 中的。这是您在使用 Java(或 C#)时必须接受的。这些不是动态语言,尽管 C# 正在添加一些形式的动态。实际上,据我所知,Ruby 没有“静态”方法——在这种情况下,这些是单例类对象上的方法。然后,您可以使用新类覆盖此单例,并且前一个类对象中的方法将调用新类中定义的方法(正确吗?)。因此,如果您在原始类的上下文中调用方法,它仍然只会执行原始静态,但是调用派生类中的方法,会调用来自父类或子类的方法。有趣,我可以看到一些价值。它需要不同的思维模式。

Since you are working in Java, you will need to adjust to that way of doing things. Why they did this? Well, probably to improve performance at the time based on the technology and understanding that was available. Computer languages are constantly evolving. Go back far enough and there is no such thing as OOP. In the future, there will be other new ideas.

由于您使用 Java 工作,因此您需要适应这种做事方式。他们为什么这样做?好吧,可能是为了根据可用的技术和理解来提高当时的性能。计算机语言在不断发展。回到足够远的地方,没有 OOP 之类的东西。未来还会有其他新的想法。

EDIT: One other comment. Now that I see the differences and as I Java/C# developer myself, I can understand why the answers you get from Java developers may be confusing if you are coming from a language like Ruby. Java staticmethods are not the same as Ruby classmethods. Java developers will have a hard time understanding this, as will conversely those who work mostly with a language like Ruby/Smalltalk. I can see how this would also be greatly confusing by the fact that Java also uses "class method" as another way to talk about static methods but this same term is used differently by Ruby. Java does not have Ruby style class methods (sorry); Ruby does not have Java style static methods which are really just old procedural style functions, as found in C.

编辑:另一条评论。现在我看到了差异,并且作为我自己的 Java/C# 开发人员,我可以理解为什么如果您来自 Ruby 之类的语言,您从 Java 开发人员那里得到的答案可能会令人困惑。Javastatic方法与 Rubyclass方法不同。Java 开发人员将很难理解这一点,相反,那些主要使用 Ruby/Smalltalk 等语言工作的开发人员也会如此。我可以看到,Java 也使用“类方法”作为谈论静态方法的另一种方式,但 Ruby 使用相同的术语,这一事实也令人困惑。Java 没有 Ruby 风格的类方法(抱歉);Ruby 没有 Java 风格的静态方法,它们实际上只是旧的过程风格函数,如在 C 中发现的那样。

By the way - thanks for the question! I learned something new for me today about class methods (Ruby style).

顺便说一句 - 谢谢你的问题!今天我学到了一些关于类方法(Ruby 风格)的新知识。

回答by pop stack

The following code shows that it is possible:

以下代码表明这是可能的:

class OverridenStaticMeth {   

static void printValue() {   
System.out.println("Overriden Meth");   
}   

}   

public class OverrideStaticMeth extends OverridenStaticMeth {   

static void printValue() {   
System.out.println("Overriding Meth");   
}   

public static void main(String[] args) {   
OverridenStaticMeth osm = new OverrideStaticMeth();   
osm.printValue();   

System.out.println("now, from main");
printValue();

}   

} 

回答by Richard JP Le Guen

Method overriding is made possible by dynamic dispatching, meaning that the declared type of an object doesn't determine its behavior, but rather its runtime type:

动态分派使方法覆盖成为可能,这意味着对象的声明类型不决定其行为,而是决定其运行时类型:

Animal lassie = new Dog();
lassie.speak(); // outputs "woof!"
Animal kermit = new Frog();
kermit.speak(); // outputs "ribbit!"

Even though both lassieand kermitare declared as objects of type Animal, their behavior (method .speak()) varies because dynamic dispatching will only bindthe method call .speak()to an implementation at run time - not at compile time.

尽管lassiekermit都被声明为类型的对象Animal,但它们的行为(方法.speak())会有所不同,因为动态分派只会在运行时将方法调用绑定.speak()到实现,而不是在编译时。

Now, here's where the statickeyword starts to make sense: the word "static" is an antonym for "dynamic".So the reason why you can't override static methods is because there is no dynamic dispatching on static members - because static literally means "not dynamic".If they dispatched dynamically (and thus could be overriden) the statickeyword just wouldn't make sense anymore.

现在,这里是static关键字开始有意义的地方:“静态”一词是“动态”的反义词。所以你不能覆盖静态方法的原因是因为静态成员没有动态调度 -因为静态的字面意思是“非动态”。如果它们是动态调度的(因此可以被覆盖),那么static关键字就不再有意义了。

回答by Steve Powell

The short answer is: it is entirely possible, but Java doesn't do it.

简短的回答是:完全有可能,但 Java 没有做到。

Here is some code which illustrates the current state of affairsin Java:

下面是一些代码,它说明了Java 中的当前状态

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

File Child.java:

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

If you run this (I did it on a Mac, from Eclipse, using Java 1.6) you get:

如果你运行这个(我在 Mac 上,从 Eclipse,使用 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.

Here, the onlycases which might be a surprise (and which the question is about) appear to be the firstcase:

在这里,唯一可能令人惊讶(以及问题所在)的情况似乎是第一种情况:

"The run-time type is not used to determine which static methods are called, even when called with an object instance (obj.staticMethod())."

“运行时类型不用于确定调用哪些静态方法,即使在使用对象实例 ( obj.staticMethod())调用时也是如此。”

and the lastcase:

去年的情况:

"When calling a static method from within an object method of a class, the static method chosen is the one accessible from the class itself and notfrom the class defining the run-time type of the object."

“当从类的对象方法中调用静态方法时,选择的静态方法是从类本身访问的方法,而不是从定义对象运行时类型的类访问的方法。”

Calling with an object instance

使用对象实例调用

The static call is resolved at compile-time, whereas a non-static method call is resolved at run-time. Notice that although static methods are inherited(from parent) they are not overridden(by child). This could be a surprise if you expected otherwise.

静态调用在编译时解析,而非静态方法调用在运行时解析。请注意,尽管静态方法是(从父级)继承的,但它们并没有(子级)覆盖。如果您另有预期,这可能会令人惊讶。

Calling from within an object method

从对象方法内部调用

Objectmethod calls are resolved using the run-time type, but static (class) method calls are resolved using the compile-time (declared) type.

对象方法调用使用运行时类型解析,但静态()方法调用使用编译时(声明)类型解析。

Changing the rules

改变规则

To change these rules, so that the last call in the example called Child.printValue(), static calls would have to be provided with a type at run-time, rather than the compiler resolving the call at compile-time with the declared class of the object (or context). Static calls could then use the (dynamic) type hierarchy to resolve the call, just as object method calls do today.

要更改这些规则,以便示例中的最后一个调用Child.printValue(),静态调用必须在运行时提供一个类型,而不是编译器在编译时使用对象的声明类(或语境)。然后静态调用可以使用(动态)类型层次结构来解析调用,就像今天的对象方法调用一样。

This would easily be doable (if we changed Java :-O), and is not at all unreasonable, however, it has some interesting considerations.

这很容易实现(如果我们更改 Java :-O),并且完全没有道理,但是,它有一些有趣的考虑。

The main consideration is that we need to decide whichstatic method calls should do this.

主要的考虑是我们需要决定哪些静态方法调用应该这样做。

At the moment, Java has this "quirk" in the language whereby obj.staticMethod()calls are replaced by ObjectClass.staticMethod()calls (normally with a warning). [Note:ObjectClassis the compile-time type of obj.] These would be good candidates for overriding in this way, taking the run-time type of obj.

目前,Java 在语言中具有这种“怪癖”,即obj.staticMethod()调用被调用替换ObjectClass.staticMethod()(通常带有警告)。[注:ObjectClass是的编译时类型obj。这些将是压倒一切以这种方式,采取的运行时类型很好的候选人obj

If we did it would make method bodies harder to read: static calls in a parent class could potentially be dynamically"re-routed". To avoid this we would have to call the static method with a class name -- and this makes the calls more obviously resolved with the compile-time type hierarchy (as now).

如果我们这样做,会使方法主体更难阅读:父类中的静态调用可能会被动态“重新路由”。为了避免这种情况,我们必须使用类名调用静态方法——这使得使用编译时类型层次结构(如现在)更明显地解析调用。

The other ways of invoking a static method are more tricky: this.staticMethod()should mean the same as obj.staticMethod(), taking the run-time type of this. However, this might cause some headaches with existing programs, which call (apparently local) static methods without decoration (which is arguably equivalent to this.method()).

调用静态方法的其他方法更棘手:this.staticMethod()应该与 含义相同obj.staticMethod(),采用 的运行时类型this。但是,这可能会给现有程序带来一些麻烦,这些程序调用(显然是本地的)静态方法而无需修饰(可以说等效于this.method())。

So what about unadorned calls staticMethod()? I suggest they do the same as today, and use the local class context to decide what to do. Otherwise great confusion would ensue. Of course it means that method()would mean this.method()if methodwas a non-static method, and ThisClass.method()if methodwere a static method. This is another source of confusion.

那么朴素的电话staticMethod()呢?我建议他们像今天一样做,并使用本地类上下文来决定要做什么。否则会引起很大的混乱。当然,method()这意味着this.method()如果method是非静态方法,ThisClass.method()如果method是静态方法。这是另一个混​​乱的来源。

Other considerations

其他注意事项

If we changed this behaviour (and made static calls potentially dynamically non-local), we would probably want to revisit the meaning of final, privateand protectedas qualifiers on staticmethods of a class. We would then all have to get used to the fact that private staticand public finalmethods are not overridden, and can therefore be safely resolved at compile-time, and are "safe" to read as local references.

如果我们改变了这种行为(并取得静态调用动态潜在的非本地),我们可能会想重温的意义finalprivateprotected为预选赛上static一个类的方法。然后我们都必须习惯这样一个事实,即private staticpublic final方法不会被覆盖,因此可以在编译时安全地解析,并且作为本地引用读取是“安全的”。