为什么Java不允许重写静态方法?

时间:2022-09-02 12:02:12

Why is it not possible to override static methods?

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

If possible, please use an example.

如果可能的话,请举一个例子。

22 个解决方案

#1


424  

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++程序员来说非常熟悉,而且速度也非常快,因为没有必要等到运行时才知道要调用哪个方法。

#2


160  

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.

这段代码不会像您预期的那样工作。也就是说,员工的奖金和普通员工一样,可以得到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.

我觉得你可能想让getbonus乘数保持不变。也许您希望能够显示所有类别的员工的奖金乘数,而不需要在每个类别中有一个雇员的实例。搜索这些示例实例的目的是什么?如果我们正在创建一个新的员工类别,并且还没有分配给它的员工呢?这在逻辑上是一个静态函数。

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处理静态的方式,我的回答是:“当然,duh。”就像我在原来的帖子里说的,它不起作用。但是如果你意味着它是糟糕的设计,与一种语言会有一些根本性的错误,这个工作,即在静力学可以覆盖虚函数一样,这将引入一个歧义或不可能实现有效的或一些这样的人,我回答说:“为什么?这个概念有什么问题?”

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.

我认为我给出的例子是很自然的。我有一个类,它有一个函数,它不依赖于任何实例数据,而且我可能非常希望调用独立于实例的实例,以及希望在实例方法中调用它。为什么这样不行?这些年来,我遇到过很多次这种情况。在实践中,我通过创建函数虚拟来绕过它,然后创建一个静态方法,它的唯一目的是成为一个静态方法,它通过一个虚拟实例将调用传递给虚拟方法。这似乎是一个非常迂回的途径。

#3


37  

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 affairs in 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 only cases which might be a surprise (and which the question is about) appear to be the first case:

在这里,唯一可能让人感到意外的案例(这个问题是关于什么的)似乎是第一个案例:

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

“运行时类型不用于确定调用哪个静态方法,即使调用对象实例(object . staticmethod())。”

and the last case:

最后一个例子:

"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 not from 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

Object method 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 which static 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: ObjectClass is the compile-time type of obj.] These would be good candidates for overriding in this way, taking the run-time type of obj.

目前,Java在语言中有这个“quirk”,即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()应该与object . staticmethod()相同,它使用了这个的运行时类型。但是,这可能会使现有程序产生一些麻烦,这些程序调用(显然是本地的)静态方法而不需要修饰(这一点可以说是等效于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 method was a non-static method, and ThisClass.method() if method were a static method. This is another source of confusion.

那么没有装饰的调用staticMethod()呢?我建议他们像今天这样做,并使用本地的类上下文来决定要做什么。否则就会产生巨大的混乱。当然,这意味着方法()将意味着this.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, private and protected as qualifiers on static methods of a class. We would then all have to get used to the fact that private static and public final methods are not overridden, and can therefore be safely resolved at compile-time, and are "safe" to read as local references.

如果我们改变了这种行为(并使静态调用成为动态的非本地调用),那么我们可能希望重新考虑final、private和protected作为类的静态方法的限定符的含义。然后,我们都必须习惯这样一个事实:私有的静态和公共的最终方法不会被重写,因此可以在编译时安全地解析,并且可以“安全地”读取作为本地引用。

#4


22  

Actually we were wrong.
Despite Java doesn't allow you to override static methods by default, if you look thoroughly through documentation of Class and Method classes in Java, you can still find a way to emulate static methods overriding by following workaround:

实际上我们错了。尽管Java不允许您在默认情况下重写静态方法,但是如果您仔细查看Java中类和方法类的文档,您仍然可以找到一种方法来模拟静态方法,通过以下方法来覆盖:

import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;

class RegularEmployee {

    private BigDecimal salary = BigDecimal.ONE;

    public void setSalary(BigDecimal salary) {
        this.salary = salary;
    }
    public static BigDecimal getBonusMultiplier() {
        return new BigDecimal(".02");
    }
    public BigDecimal calculateBonus() {
        return salary.multiply(this.getBonusMultiplier());
    }
    public BigDecimal calculateOverridenBonus() {
        try {
            // System.out.println(this.getClass().getDeclaredMethod(
            // "getBonusMultiplier").toString());
            try {
                return salary.multiply((BigDecimal) this.getClass()
                    .getDeclaredMethod("getBonusMultiplier").invoke(this));
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        }
        return null;
    }
    // ... presumably lots of other code ...
}

final class SpecialEmployee extends RegularEmployee {

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

public class StaticTestCoolMain {

    static public void main(String[] args) {
        RegularEmployee Alan = new RegularEmployee();
        System.out.println(Alan.calculateBonus());
        System.out.println(Alan.calculateOverridenBonus());
        SpecialEmployee Bob = new SpecialEmployee();
        System.out.println(Bob.calculateBonus());
        System.out.println(Bob.calculateOverridenBonus());
    }
}

Resulting output:

输出结果:

0.02
0.02
0.02
0.03

what we were trying to achieve :)

我们想要达到的目标是:

Even if we declare third variable Carl as RegularEmployee and assign to it instance of SpecialEmployee, we will still have call of RegularEmployee method in first case and call of SpecialEmployee method in second case

即使我们将第三个变量Carl声明为常规员工,并将其分配给it员工,我们仍然会在第一个案例中调用常规员工方法,并在第二种情况下调用SpecialEmployee方法。

RegularEmployee Carl = new SpecialEmployee();

System.out.println(Carl.calculateBonus());
System.out.println(Carl.calculateOverridenBonus());

just look at output console:

看看输出控制台:

0.02
0.03

;)

,)

#5


16  

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 overload static method, that's ok. But you can not override a 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 this nor super in 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.

你可以在课堂上进行反思,但它会停留在那里。您不会使用clazz1.staticMethod()来调用静态方法,而是使用MyClass.staticMethod()。静态方法不绑定到对象,因此在静态方法中不存在这种或超级的概念。静态方法是全局函数;因此,也没有多态性的概念,因此,方法覆盖没有意义。

But this could be possible if MyClass was 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中提出警告。我不知道他们为什么会允许这个捷径。

#6


9  

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 lassie and kermit are declared as objects of type Animal, their behavior (method .speak()) varies because dynamic dispatching will only bind the method call .speak() to an implementation at run time - not at compile time.

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

Now, here's where the static keyword 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 static keyword just wouldn't make sense anymore.

现在,这里是静态关键字开始有意义的地方:“静态”这个词是“动态”的反义词。所以不能重写静态方法的原因是静态成员没有动态调度——因为静态的字面意思是“不动态的”。如果他们动态地发送(因此可能是overriden),静态关键字就不再有意义了。

#7


5  

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语言中,但我不能为所有人说话;而有些则没有静态的,所有的方法都有一个固定的签名——参数和类型。在虚拟方法中,第一个参数是隐含的:引用对象本身,当从对象内部调用时,编译器会自动添加这个参数。

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.

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

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?

当有人在评论中问道:你想要这个功能的原因和目的是什么?

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 static methods are not the same as Ruby class methods. 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#开发人员,我可以理解为什么您从Java开发人员那里得到的答案可能会让您感到困惑,如果您使用的是Ruby这样的语言。Java静态方法与Ruby类方法不一样。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风格)。

#8


5  

Well... the answer is NO if you think from the perspective of how an overriden method should behave in Java. But, you don't get any compiler error if you try to override a static method. That means, if you try to override, Java doesn't stop you doing that; but you certainly don't get the same effect as you get for non-static methods. Overriding in Java simply means that the particular method would be called based on the run time type of the object and not on the compile time type of it (which is the case with overriden static methods). Okay... any guesses for the reason why do they behave strangely? Because they are class methods and hence access to them is always resolved during compile time only using the compile time type information. Accessing them using object references is just an extra liberty given by the designers of Java and we should certainly not think of stopping that practice only when they restrict it :-)

嗯…如果您从overriden方法在Java中表现的角度来思考,答案是否定的。但是,如果试图重写静态方法,就不会得到任何编译器错误。这意味着,如果你试图重写,Java不会阻止你这么做;但你肯定不会得到与非静态方法相同的效果。在Java中重写只是意味着特定的方法将基于对象的运行时类型调用,而不是基于编译时类型(这是overriden静态方法的例子)。好吧……猜猜看,为什么它们的行为很奇怪?因为它们是类方法,因此访问它们的方法总是在编译时使用编译时类型信息来解决。使用对象引用访问它们只是Java设计者的一种额外的*,我们当然不应该考虑在限制它时停止这种做法:-)

Example: let's try to see what happens if we try overriding a static method:-

例子:让我们试着看看如果我们尝试重写静态方法会发生什么:-。

class SuperClass {
// ......
public static void staticMethod() {
    System.out.println("SuperClass: inside staticMethod");
}
// ......
}

public class SubClass extends SuperClass {
// ......
// overriding the static method
public static void staticMethod() {
    System.out.println("SubClass: inside staticMethod");
}

// ......
public static void main(String[] args) {
    // ......
    SuperClass superClassWithSuperCons = new SuperClass();
    SuperClass superClassWithSubCons = new SubClass();
    SubClass subClassWithSubCons = new SubClass();

    superClassWithSuperCons.staticMethod();
    superClassWithSubCons.staticMethod();
    subClassWithSubCons.staticMethod();
    // ...
}
}

Output:-
SuperClass: inside staticMethod
SuperClass: inside staticMethod
SubClass: inside staticMethod

输出:-超类:内部静态方法超类:内部staticMethod子类:内部静态方法。

Notice the second line of the output. Had the staticMethod been overriden this line should have been identical to the third line as we're invoking the 'staticMethod()' on an object of Runtime Type as 'SubClass' and not as 'SuperClass'. This confirms that the static methods are always resolved using their compile time type information only.

注意输出的第二行。如果staticMethod是overriden,这一行应该与第三行相同,因为我们在运行时类型的对象上调用“staticMethod()”作为“子类”,而不是“超类”。这证实了静态方法总是使用它们的编译时类型信息来解决。

#9


4  

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?

一般来说,允许“重写”静态方法是没有意义的,因为没有什么好方法来决定在运行时调用哪一个。以雇员为例,如果我们调用regularemployee.getbonus乘数()——该方法应该被执行?

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中,可以想象一种语言定义,只要通过对象实例调用它们,就可以“覆盖”静态方法。但是,所有这些都是为了重新实现常规的类方法,在不添加任何好处的情况下增加语言的冗余。

#10


4  

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.

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

#11


4  

I like and double Jay's comment (https://*.com/a/2223803/1517187).
I agree that this is bad design of Java.
Many other languages support overriding static methods, as we see in previous comments. I feel Jay has also come to Java from Delphi like me.
Delphi (Object Pascal) was the first language implementing OOP.
It is obvious that many people had experience with that language, since it was in the past the only language to write commercial GUI products. And - yes, we could in Delphi override static methods. Actually, static methods in Delphi are called "class methods", while Delphi had different concept of "Delphi static methods" which were methods with early binding. To override methods you had to use late binding, declare "virtual" directive. So it was very convenient and intuitive and I would expect this in Java.

我喜欢和双重Jay的评论(https://*.com/a/2223803/1517187)。我同意这是Java糟糕的设计。正如我们在前面的注释中看到的,许多其他语言支持覆盖静态方法。我觉得Jay也像我一样从Delphi来到Java。Delphi (Object Pascal)是第一个实现OOP的语言。很明显,许多人都有这种语言的经验,因为它是过去唯一一种编写商业GUI产品的语言。是的,我们可以在Delphi重写静态方法。实际上,Delphi中的静态方法被称为“类方法”,而Delphi则有不同的“Delphi静态方法”的概念,即具有早期绑定的方法。要覆盖必须使用后期绑定的方法,请声明“虚拟”指令。它非常方便直观,我希望用Java。

#12


4  

Yes..Practically Java's Allows to override static method...And No Theoretically......If you Override a static method in Java then it will compile and run smoothly..but it will lose Polymorphism....which is basic property of Java ..You will Read Everywhere that its not possible try yourself compling and running..you will get your answer...e.g..If you Have Class Animal and a static method eat() and you Override that static method in its Subclass lets called it Dog..then when wherever you Assign a Dog object to an Animal Reference and call eat()..according to Java Dog's eat() should have been called..but in static Overriding Animals's eat() will Called..

是的. .实际上,Java允许覆盖静态方法…理论上,没有……如果您在Java中覆盖了静态方法,那么它将会顺利地编译和运行。但它将失去多态性....这是Java的基本属性。4 .你会在任何地方读到自己不可能做到的事。你会得到答案的。如果您有类动物和静态方法eat(),并在其子类中重写该静态方法,我们称之为Dog..然后,当你将狗对象分配给动物引用并调用eat()时根据Java Dog's eat()应该被调用。但是在静态覆盖动物的饮食中()会被称为…

class Animal {
    public static void eat() {
        System.out.println("Animal Eating");
    }
}

class Dog extends Animal{
    public static void eat() {
        System.out.println("Dog Eating");
    }
}

class Test {
    public static void main(String args[]) {
       Animal obj= new Dog();//Dog object in animal
       obj.eat(); //should call dog's eat but it didn't
    }
}


Output Animal Eating

According to Polymorphism Principle of Java the Output Should be Dog Eating.
But the result was different because to support Polymorphism Java uses Late Binding that means methods are called only at the run-time but not in the case of static methods..In static methods compiler calls methods at the compile time rather than the run-time..so we get methods according to the reference and not according to the object a reference a containing..that's why You can say Practically it supports static overring but theoretically it doesn't...

根据Java的多态原理,输出应该是狗食。但是结果是不同的,因为支持多态性Java使用后期绑定,这意味着方法只在运行时调用,而不是在静态方法的情况下调用。在静态方法中,编译器在编译时调用方法而不是运行时。因此,我们根据引用来获取方法,而不是根据对象引用一个包含的引用。这就是为什么你可以说实际上它支持静态覆盖但理论上它不支持。

#13


3  

By overriding we can create a polymorphic nature depending on the object type. Static method has no relation with object. So java can not support static method overriding.

通过重写,我们可以根据对象类型创建多态性质。静态方法与对象无关。所以java不能支持静态方法覆盖。

#14


2  

Overriding in Java simply means that the particular method would be called based on the run time type of the object and not on the compile time type of it (which is the case with overriden static methods). As static methods are class methods they are notinstance methods so they have nothing to do with the fact which reference is pointing to which Object or instance.as per the nature of static method it belongs to specific class, but you can redeclare it in to the subclass but that subclass doesn't know anything about the parent class' static methods because as I said it is specific to only that class in which it has been declared .Accessing them using object references is just an extra liberty given by the designers of Java and we should certainly not think of stopping that practice only when they restrict it more details and example http://faisalbhagat.blogspot.com/2014/09/method-overriding-and-method-hiding.html

在Java中重写只是意味着特定的方法将基于对象的运行时类型调用,而不是基于编译时类型(这是overriden静态方法的例子)。静态方法是类方法,它们是notinstance方法,所以它们与引用指向哪个对象或实例无关。根据静态方法的性质,它属于特定的类,但是你可以重新定义子类的子类,但不知道任何关于父类的静态方法,因为我只说,这是特定于这个类的使用对象引用已经宣布.Accessing它们只是一个额外的*由Java的设计者,我们当然不应该认为停止练习只有当他们限制更多的细节和例子http://faisalbhagat.blogspot.com/2014/09/method-overriding-and-method-hiding.html

#15


2  

Answer of this question is simple, the method or variable marked as static belongs to the class only, So that static method cannot be inherited in the sub class because they belong to the super class only.

这个问题的答案很简单,静态的方法或变量只属于类,所以静态方法不能在子类中继承,因为它们只属于超类。

#16


1  

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 can call static methods through an instance. Generally nobody does that. My bad.

编辑:在语言设计中,通过一个不幸的疏忽,您可以通过实例调用静态方法。一般没人呢。我的坏。

#17


1  

By overriding, you achieve dynamic polymorhpism. When you say overridng static methods, the words you are trying to use are contradictory.

通过重写,您可以实现动态的多态性。当你说overridng静态方法时,你试图使用的词是矛盾的。

Static says - compile time, overriding is used for dynamic polymorphism. Both are opposite in nature, and hence can't be used together.

静态表示-编译时,重写用于动态多态性。两者在本质上都是对立的,因此不能在一起使用。

Dynamic polymorhpic behavior comes when programmer uses an object and accessing an instance method. JRE will map different instance methods of different classes based on what kind of object you are using.

当程序员使用一个对象并访问一个实例方法时,动态的多态性行为就出现了。JRE将根据您使用的对象类型映射不同类的不同实例方法。

When you say overriding static methods, static methods we will access by using class name, which will be linked at compile time, so there is no concept of linking methods at run time with static methods. So the term "overriding" static methods itself doesn't make any meaning.

当您说重写静态方法时,我们将使用类名访问静态方法,它将在编译时链接,因此在运行时没有使用静态方法链接方法的概念。因此,“覆盖”静态方法本身并没有任何意义。

Note: even if you access a class method with an object, still java compiler is intelligent enough to find it out, and will do static linking.

注意:即使您使用对象访问类方法,java编译器仍然足够智能,能够找到它,并将进行静态链接。

#18


1  

Easy solution: Use singleton instance. It will allow overrides and inheritance.

简单解决方案:使用singleton实例。它将允许覆盖和继承。

In my system, I have SingletonsRegistry class, which returns instance for passed Class. If instance is not found, it is created.

在我的系统中,我有SingletonsRegistry类,它返回通过类的实例。如果没有找到实例,就创建它。

Haxe language class:

可把语言类:

package rflib.common.utils;
import haxe.ds.ObjectMap;



class SingletonsRegistry
{
  public static var instances:Map<Class<Dynamic>, Dynamic>;

  static function __init__()
  {
    StaticsInitializer.addCallback(SingletonsRegistry, function()
    {
      instances = null;
    });

  } 

  public static function getInstance(cls:Class<Dynamic>, ?args:Array<Dynamic>)
  {
    if (instances == null) {
      instances = untyped new ObjectMap<Dynamic, Dynamic>();      
    }

    if (!instances.exists(cls)) 
    {
      if (args == null) args = [];
      instances.set(cls, Type.createInstance(cls, args));
    }

    return instances.get(cls);
  }


  public static function validate(inst:Dynamic, cls:Class<Dynamic>)
  {
    if (instances == null) return;

    var inst2 = instances[cls];
    if (inst2 != null && inst != inst2) throw "Can\'t create multiple instances of " + Type.getClassName(cls) + " - it's singleton!";
  }

}

#19


1  

Here is a simple explanation.A static method is associated with a class while an instance method is associated with a particular object.Overrides allow to call different implementation of the overridden methods associated with the particular object. So it is counter-intuitive to override static method which is not even associated with objects but class itself in the first place.So static methods cannot be overridden based on what object is calling it, it will always be associated with the class where it was created.

这里有一个简单的解释。静态方法与类相关联,而实例方法与特定对象关联。覆盖允许调用与特定对象关联的覆盖方法的不同实现。因此,重写静态方法是违反直觉的,它甚至不与对象关联,而是在一开始就把类本身关联起来。因此,静态方法不能基于对象的调用而被重写,它总是与创建它的类相关联。

#20


1  

A Static method, variable, block or nested class belongs to the entire class rather than an object.

静态方法、变量、块或嵌套类属于整个类,而不是对象。

A Method in Java is used to expose the behaviour of an Object / Class. Here, as the method is static (i.e, static method is used to represent the behaviour of a class only.) changing/ overriding the behaviour of entire class will violate the phenomenon of one of the fundamental pillar of Object oriented programming i.e, high cohesion. (remember a constructor is a special kind of method in Java.)

Java中的方法用于公开对象/类的行为。这里,由于方法是静态的(i。静态方法是用来表示类的行为的。)改变/覆盖整个类的行为将会违反面向对象编程i的基本支柱之一的现象。e,高内聚。(在Java中,构造函数是一种特殊的方法。)

High Cohesion - One class should have only one role. For example: A car class should produce only car objects and not bike, trucks, planes etc. But the Car class may have some features(behaviour) that belongs to itself only.

高内聚性——一个类应该只有一个角色。例如:汽车类应该只生产汽车对象,而不是自行车、卡车、飞机等。但是汽车类可能有一些属于自己的特性(行为)。

Therefore, while designing the java programming language. The language designers thought to allow developers to keep some behaviours of a class to itself only by making a method static in nature.

因此,在设计java编程语言时。语言设计者认为允许开发人员仅通过在本质上静态的方法来保持类的某些行为。


The below piece code tries to override the static method, but will not encounter any compilation error.

下面的代码尝试重写静态方法,但是不会遇到任何编译错误。

public class Vehicle {
static int VIN;

public static int getVehileNumber() {
    return VIN;
}}

class Car extends Vehicle {
static int carNumber;

public static int getVehileNumber() {
    return carNumber;
}}

This is because, here we are not overriding a method but we are just re-declaring it. Java allows re-declaration of a method (static/non-static).

这是因为,这里我们不是重写方法,而是重新声明它。Java允许重新声明方法(静态/非静态)。

Removing the static keyword from getVehileNumber() method of Car class will result into compilation error, Since, we are trying to change the functionality of static method which belongs to Vehicle class only.

从Car类的getVehileNumber()方法中删除静态关键字将导致编译错误,因为我们正在尝试改变静态方法的功能,而静态方法只属于Vehicle类。

Also, If the getVehileNumber() is declared as final then the code will not compile, Since the final keyword restricts the programmer from re-declaring the method.

另外,如果将getVehileNumber()声明为final,那么代码就不会编译,因为final关键字限制了程序员重新声明方法。

public static final int getVehileNumber() {
return VIN;     }

Overall, this is upto software designers for where to use the static methods. I personally prefer to use static methods to perform some actions without creating any instance of a class. Secondly, to hide the behaviour of a class from outside world.

总的来说,这是软件设计人员使用静态方法的原因。我个人倾向于使用静态方法来执行一些操作,而不需要创建类的任何实例。其次,隐藏来自外部世界的行为。

#21


-1  

Now seeing above answers everyone knows that we can't override static methods, but one should not misunderstood about the concept of accessing static methods from subclass.

现在看到上面的答案,每个人都知道我们不能重写静态方法,但是我们不应该误解从子类访问静态方法的概念。

We can access static methods of super class with subclass reference if this static method has not been hidden by new static method defined in sub class.

如果静态方法没有被子类中定义的新静态方法隐藏,那么我们可以使用子类引用来访问超类的静态方法。

For Example, see below code:-

例如,参见下面的代码:-。

public class StaticMethodsHiding {
    public static void main(String[] args) {
        SubClass.hello();
    }
}


class SuperClass {
    static void hello(){
        System.out.println("SuperClass saying Hello");
    }
}


class SubClass extends SuperClass {
    // static void hello() {
    // System.out.println("SubClass Hello");
    // }
}

Output:-

输出:

SuperClass saying Hello

See Java oracle docs and search for What You Can Do in a Subclass for details about hiding of static methods in sub class.

请参阅Java oracle文档,并在子类中搜索您可以在子类中做什么,以了解在子类中隐藏静态方法的细节。

Thanks

谢谢

#22


-3  

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

}   

} 

#1


424  

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++程序员来说非常熟悉,而且速度也非常快,因为没有必要等到运行时才知道要调用哪个方法。

#2


160  

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.

这段代码不会像您预期的那样工作。也就是说,员工的奖金和普通员工一样,可以得到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.

我觉得你可能想让getbonus乘数保持不变。也许您希望能够显示所有类别的员工的奖金乘数,而不需要在每个类别中有一个雇员的实例。搜索这些示例实例的目的是什么?如果我们正在创建一个新的员工类别,并且还没有分配给它的员工呢?这在逻辑上是一个静态函数。

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处理静态的方式,我的回答是:“当然,duh。”就像我在原来的帖子里说的,它不起作用。但是如果你意味着它是糟糕的设计,与一种语言会有一些根本性的错误,这个工作,即在静力学可以覆盖虚函数一样,这将引入一个歧义或不可能实现有效的或一些这样的人,我回答说:“为什么?这个概念有什么问题?”

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.

我认为我给出的例子是很自然的。我有一个类,它有一个函数,它不依赖于任何实例数据,而且我可能非常希望调用独立于实例的实例,以及希望在实例方法中调用它。为什么这样不行?这些年来,我遇到过很多次这种情况。在实践中,我通过创建函数虚拟来绕过它,然后创建一个静态方法,它的唯一目的是成为一个静态方法,它通过一个虚拟实例将调用传递给虚拟方法。这似乎是一个非常迂回的途径。

#3


37  

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 affairs in 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 only cases which might be a surprise (and which the question is about) appear to be the first case:

在这里,唯一可能让人感到意外的案例(这个问题是关于什么的)似乎是第一个案例:

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

“运行时类型不用于确定调用哪个静态方法,即使调用对象实例(object . staticmethod())。”

and the last case:

最后一个例子:

"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 not from 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

Object method 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 which static 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: ObjectClass is the compile-time type of obj.] These would be good candidates for overriding in this way, taking the run-time type of obj.

目前,Java在语言中有这个“quirk”,即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()应该与object . staticmethod()相同,它使用了这个的运行时类型。但是,这可能会使现有程序产生一些麻烦,这些程序调用(显然是本地的)静态方法而不需要修饰(这一点可以说是等效于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 method was a non-static method, and ThisClass.method() if method were a static method. This is another source of confusion.

那么没有装饰的调用staticMethod()呢?我建议他们像今天这样做,并使用本地的类上下文来决定要做什么。否则就会产生巨大的混乱。当然,这意味着方法()将意味着this.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, private and protected as qualifiers on static methods of a class. We would then all have to get used to the fact that private static and public final methods are not overridden, and can therefore be safely resolved at compile-time, and are "safe" to read as local references.

如果我们改变了这种行为(并使静态调用成为动态的非本地调用),那么我们可能希望重新考虑final、private和protected作为类的静态方法的限定符的含义。然后,我们都必须习惯这样一个事实:私有的静态和公共的最终方法不会被重写,因此可以在编译时安全地解析,并且可以“安全地”读取作为本地引用。

#4


22  

Actually we were wrong.
Despite Java doesn't allow you to override static methods by default, if you look thoroughly through documentation of Class and Method classes in Java, you can still find a way to emulate static methods overriding by following workaround:

实际上我们错了。尽管Java不允许您在默认情况下重写静态方法,但是如果您仔细查看Java中类和方法类的文档,您仍然可以找到一种方法来模拟静态方法,通过以下方法来覆盖:

import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;

class RegularEmployee {

    private BigDecimal salary = BigDecimal.ONE;

    public void setSalary(BigDecimal salary) {
        this.salary = salary;
    }
    public static BigDecimal getBonusMultiplier() {
        return new BigDecimal(".02");
    }
    public BigDecimal calculateBonus() {
        return salary.multiply(this.getBonusMultiplier());
    }
    public BigDecimal calculateOverridenBonus() {
        try {
            // System.out.println(this.getClass().getDeclaredMethod(
            // "getBonusMultiplier").toString());
            try {
                return salary.multiply((BigDecimal) this.getClass()
                    .getDeclaredMethod("getBonusMultiplier").invoke(this));
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        }
        return null;
    }
    // ... presumably lots of other code ...
}

final class SpecialEmployee extends RegularEmployee {

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

public class StaticTestCoolMain {

    static public void main(String[] args) {
        RegularEmployee Alan = new RegularEmployee();
        System.out.println(Alan.calculateBonus());
        System.out.println(Alan.calculateOverridenBonus());
        SpecialEmployee Bob = new SpecialEmployee();
        System.out.println(Bob.calculateBonus());
        System.out.println(Bob.calculateOverridenBonus());
    }
}

Resulting output:

输出结果:

0.02
0.02
0.02
0.03

what we were trying to achieve :)

我们想要达到的目标是:

Even if we declare third variable Carl as RegularEmployee and assign to it instance of SpecialEmployee, we will still have call of RegularEmployee method in first case and call of SpecialEmployee method in second case

即使我们将第三个变量Carl声明为常规员工,并将其分配给it员工,我们仍然会在第一个案例中调用常规员工方法,并在第二种情况下调用SpecialEmployee方法。

RegularEmployee Carl = new SpecialEmployee();

System.out.println(Carl.calculateBonus());
System.out.println(Carl.calculateOverridenBonus());

just look at output console:

看看输出控制台:

0.02
0.03

;)

,)

#5


16  

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 overload static method, that's ok. But you can not override a 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 this nor super in 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.

你可以在课堂上进行反思,但它会停留在那里。您不会使用clazz1.staticMethod()来调用静态方法,而是使用MyClass.staticMethod()。静态方法不绑定到对象,因此在静态方法中不存在这种或超级的概念。静态方法是全局函数;因此,也没有多态性的概念,因此,方法覆盖没有意义。

But this could be possible if MyClass was 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中提出警告。我不知道他们为什么会允许这个捷径。

#6


9  

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 lassie and kermit are declared as objects of type Animal, their behavior (method .speak()) varies because dynamic dispatching will only bind the method call .speak() to an implementation at run time - not at compile time.

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

Now, here's where the static keyword 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 static keyword just wouldn't make sense anymore.

现在,这里是静态关键字开始有意义的地方:“静态”这个词是“动态”的反义词。所以不能重写静态方法的原因是静态成员没有动态调度——因为静态的字面意思是“不动态的”。如果他们动态地发送(因此可能是overriden),静态关键字就不再有意义了。

#7


5  

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语言中,但我不能为所有人说话;而有些则没有静态的,所有的方法都有一个固定的签名——参数和类型。在虚拟方法中,第一个参数是隐含的:引用对象本身,当从对象内部调用时,编译器会自动添加这个参数。

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.

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

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?

当有人在评论中问道:你想要这个功能的原因和目的是什么?

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 static methods are not the same as Ruby class methods. 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#开发人员,我可以理解为什么您从Java开发人员那里得到的答案可能会让您感到困惑,如果您使用的是Ruby这样的语言。Java静态方法与Ruby类方法不一样。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风格)。

#8


5  

Well... the answer is NO if you think from the perspective of how an overriden method should behave in Java. But, you don't get any compiler error if you try to override a static method. That means, if you try to override, Java doesn't stop you doing that; but you certainly don't get the same effect as you get for non-static methods. Overriding in Java simply means that the particular method would be called based on the run time type of the object and not on the compile time type of it (which is the case with overriden static methods). Okay... any guesses for the reason why do they behave strangely? Because they are class methods and hence access to them is always resolved during compile time only using the compile time type information. Accessing them using object references is just an extra liberty given by the designers of Java and we should certainly not think of stopping that practice only when they restrict it :-)

嗯…如果您从overriden方法在Java中表现的角度来思考,答案是否定的。但是,如果试图重写静态方法,就不会得到任何编译器错误。这意味着,如果你试图重写,Java不会阻止你这么做;但你肯定不会得到与非静态方法相同的效果。在Java中重写只是意味着特定的方法将基于对象的运行时类型调用,而不是基于编译时类型(这是overriden静态方法的例子)。好吧……猜猜看,为什么它们的行为很奇怪?因为它们是类方法,因此访问它们的方法总是在编译时使用编译时类型信息来解决。使用对象引用访问它们只是Java设计者的一种额外的*,我们当然不应该考虑在限制它时停止这种做法:-)

Example: let's try to see what happens if we try overriding a static method:-

例子:让我们试着看看如果我们尝试重写静态方法会发生什么:-。

class SuperClass {
// ......
public static void staticMethod() {
    System.out.println("SuperClass: inside staticMethod");
}
// ......
}

public class SubClass extends SuperClass {
// ......
// overriding the static method
public static void staticMethod() {
    System.out.println("SubClass: inside staticMethod");
}

// ......
public static void main(String[] args) {
    // ......
    SuperClass superClassWithSuperCons = new SuperClass();
    SuperClass superClassWithSubCons = new SubClass();
    SubClass subClassWithSubCons = new SubClass();

    superClassWithSuperCons.staticMethod();
    superClassWithSubCons.staticMethod();
    subClassWithSubCons.staticMethod();
    // ...
}
}

Output:-
SuperClass: inside staticMethod
SuperClass: inside staticMethod
SubClass: inside staticMethod

输出:-超类:内部静态方法超类:内部staticMethod子类:内部静态方法。

Notice the second line of the output. Had the staticMethod been overriden this line should have been identical to the third line as we're invoking the 'staticMethod()' on an object of Runtime Type as 'SubClass' and not as 'SuperClass'. This confirms that the static methods are always resolved using their compile time type information only.

注意输出的第二行。如果staticMethod是overriden,这一行应该与第三行相同,因为我们在运行时类型的对象上调用“staticMethod()”作为“子类”,而不是“超类”。这证实了静态方法总是使用它们的编译时类型信息来解决。

#9


4  

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?

一般来说,允许“重写”静态方法是没有意义的,因为没有什么好方法来决定在运行时调用哪一个。以雇员为例,如果我们调用regularemployee.getbonus乘数()——该方法应该被执行?

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中,可以想象一种语言定义,只要通过对象实例调用它们,就可以“覆盖”静态方法。但是,所有这些都是为了重新实现常规的类方法,在不添加任何好处的情况下增加语言的冗余。

#10


4  

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.

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

#11


4  

I like and double Jay's comment (https://*.com/a/2223803/1517187).
I agree that this is bad design of Java.
Many other languages support overriding static methods, as we see in previous comments. I feel Jay has also come to Java from Delphi like me.
Delphi (Object Pascal) was the first language implementing OOP.
It is obvious that many people had experience with that language, since it was in the past the only language to write commercial GUI products. And - yes, we could in Delphi override static methods. Actually, static methods in Delphi are called "class methods", while Delphi had different concept of "Delphi static methods" which were methods with early binding. To override methods you had to use late binding, declare "virtual" directive. So it was very convenient and intuitive and I would expect this in Java.

我喜欢和双重Jay的评论(https://*.com/a/2223803/1517187)。我同意这是Java糟糕的设计。正如我们在前面的注释中看到的,许多其他语言支持覆盖静态方法。我觉得Jay也像我一样从Delphi来到Java。Delphi (Object Pascal)是第一个实现OOP的语言。很明显,许多人都有这种语言的经验,因为它是过去唯一一种编写商业GUI产品的语言。是的,我们可以在Delphi重写静态方法。实际上,Delphi中的静态方法被称为“类方法”,而Delphi则有不同的“Delphi静态方法”的概念,即具有早期绑定的方法。要覆盖必须使用后期绑定的方法,请声明“虚拟”指令。它非常方便直观,我希望用Java。

#12


4  

Yes..Practically Java's Allows to override static method...And No Theoretically......If you Override a static method in Java then it will compile and run smoothly..but it will lose Polymorphism....which is basic property of Java ..You will Read Everywhere that its not possible try yourself compling and running..you will get your answer...e.g..If you Have Class Animal and a static method eat() and you Override that static method in its Subclass lets called it Dog..then when wherever you Assign a Dog object to an Animal Reference and call eat()..according to Java Dog's eat() should have been called..but in static Overriding Animals's eat() will Called..

是的. .实际上,Java允许覆盖静态方法…理论上,没有……如果您在Java中覆盖了静态方法,那么它将会顺利地编译和运行。但它将失去多态性....这是Java的基本属性。4 .你会在任何地方读到自己不可能做到的事。你会得到答案的。如果您有类动物和静态方法eat(),并在其子类中重写该静态方法,我们称之为Dog..然后,当你将狗对象分配给动物引用并调用eat()时根据Java Dog's eat()应该被调用。但是在静态覆盖动物的饮食中()会被称为…

class Animal {
    public static void eat() {
        System.out.println("Animal Eating");
    }
}

class Dog extends Animal{
    public static void eat() {
        System.out.println("Dog Eating");
    }
}

class Test {
    public static void main(String args[]) {
       Animal obj= new Dog();//Dog object in animal
       obj.eat(); //should call dog's eat but it didn't
    }
}


Output Animal Eating

According to Polymorphism Principle of Java the Output Should be Dog Eating.
But the result was different because to support Polymorphism Java uses Late Binding that means methods are called only at the run-time but not in the case of static methods..In static methods compiler calls methods at the compile time rather than the run-time..so we get methods according to the reference and not according to the object a reference a containing..that's why You can say Practically it supports static overring but theoretically it doesn't...

根据Java的多态原理,输出应该是狗食。但是结果是不同的,因为支持多态性Java使用后期绑定,这意味着方法只在运行时调用,而不是在静态方法的情况下调用。在静态方法中,编译器在编译时调用方法而不是运行时。因此,我们根据引用来获取方法,而不是根据对象引用一个包含的引用。这就是为什么你可以说实际上它支持静态覆盖但理论上它不支持。

#13


3  

By overriding we can create a polymorphic nature depending on the object type. Static method has no relation with object. So java can not support static method overriding.

通过重写,我们可以根据对象类型创建多态性质。静态方法与对象无关。所以java不能支持静态方法覆盖。

#14


2  

Overriding in Java simply means that the particular method would be called based on the run time type of the object and not on the compile time type of it (which is the case with overriden static methods). As static methods are class methods they are notinstance methods so they have nothing to do with the fact which reference is pointing to which Object or instance.as per the nature of static method it belongs to specific class, but you can redeclare it in to the subclass but that subclass doesn't know anything about the parent class' static methods because as I said it is specific to only that class in which it has been declared .Accessing them using object references is just an extra liberty given by the designers of Java and we should certainly not think of stopping that practice only when they restrict it more details and example http://faisalbhagat.blogspot.com/2014/09/method-overriding-and-method-hiding.html

在Java中重写只是意味着特定的方法将基于对象的运行时类型调用,而不是基于编译时类型(这是overriden静态方法的例子)。静态方法是类方法,它们是notinstance方法,所以它们与引用指向哪个对象或实例无关。根据静态方法的性质,它属于特定的类,但是你可以重新定义子类的子类,但不知道任何关于父类的静态方法,因为我只说,这是特定于这个类的使用对象引用已经宣布.Accessing它们只是一个额外的*由Java的设计者,我们当然不应该认为停止练习只有当他们限制更多的细节和例子http://faisalbhagat.blogspot.com/2014/09/method-overriding-and-method-hiding.html

#15


2  

Answer of this question is simple, the method or variable marked as static belongs to the class only, So that static method cannot be inherited in the sub class because they belong to the super class only.

这个问题的答案很简单,静态的方法或变量只属于类,所以静态方法不能在子类中继承,因为它们只属于超类。

#16


1  

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 can call static methods through an instance. Generally nobody does that. My bad.

编辑:在语言设计中,通过一个不幸的疏忽,您可以通过实例调用静态方法。一般没人呢。我的坏。

#17


1  

By overriding, you achieve dynamic polymorhpism. When you say overridng static methods, the words you are trying to use are contradictory.

通过重写,您可以实现动态的多态性。当你说overridng静态方法时,你试图使用的词是矛盾的。

Static says - compile time, overriding is used for dynamic polymorphism. Both are opposite in nature, and hence can't be used together.

静态表示-编译时,重写用于动态多态性。两者在本质上都是对立的,因此不能在一起使用。

Dynamic polymorhpic behavior comes when programmer uses an object and accessing an instance method. JRE will map different instance methods of different classes based on what kind of object you are using.

当程序员使用一个对象并访问一个实例方法时,动态的多态性行为就出现了。JRE将根据您使用的对象类型映射不同类的不同实例方法。

When you say overriding static methods, static methods we will access by using class name, which will be linked at compile time, so there is no concept of linking methods at run time with static methods. So the term "overriding" static methods itself doesn't make any meaning.

当您说重写静态方法时,我们将使用类名访问静态方法,它将在编译时链接,因此在运行时没有使用静态方法链接方法的概念。因此,“覆盖”静态方法本身并没有任何意义。

Note: even if you access a class method with an object, still java compiler is intelligent enough to find it out, and will do static linking.

注意:即使您使用对象访问类方法,java编译器仍然足够智能,能够找到它,并将进行静态链接。

#18


1  

Easy solution: Use singleton instance. It will allow overrides and inheritance.

简单解决方案:使用singleton实例。它将允许覆盖和继承。

In my system, I have SingletonsRegistry class, which returns instance for passed Class. If instance is not found, it is created.

在我的系统中,我有SingletonsRegistry类,它返回通过类的实例。如果没有找到实例,就创建它。

Haxe language class:

可把语言类:

package rflib.common.utils;
import haxe.ds.ObjectMap;



class SingletonsRegistry
{
  public static var instances:Map<Class<Dynamic>, Dynamic>;

  static function __init__()
  {
    StaticsInitializer.addCallback(SingletonsRegistry, function()
    {
      instances = null;
    });

  } 

  public static function getInstance(cls:Class<Dynamic>, ?args:Array<Dynamic>)
  {
    if (instances == null) {
      instances = untyped new ObjectMap<Dynamic, Dynamic>();      
    }

    if (!instances.exists(cls)) 
    {
      if (args == null) args = [];
      instances.set(cls, Type.createInstance(cls, args));
    }

    return instances.get(cls);
  }


  public static function validate(inst:Dynamic, cls:Class<Dynamic>)
  {
    if (instances == null) return;

    var inst2 = instances[cls];
    if (inst2 != null && inst != inst2) throw "Can\'t create multiple instances of " + Type.getClassName(cls) + " - it's singleton!";
  }

}

#19


1  

Here is a simple explanation.A static method is associated with a class while an instance method is associated with a particular object.Overrides allow to call different implementation of the overridden methods associated with the particular object. So it is counter-intuitive to override static method which is not even associated with objects but class itself in the first place.So static methods cannot be overridden based on what object is calling it, it will always be associated with the class where it was created.

这里有一个简单的解释。静态方法与类相关联,而实例方法与特定对象关联。覆盖允许调用与特定对象关联的覆盖方法的不同实现。因此,重写静态方法是违反直觉的,它甚至不与对象关联,而是在一开始就把类本身关联起来。因此,静态方法不能基于对象的调用而被重写,它总是与创建它的类相关联。

#20


1  

A Static method, variable, block or nested class belongs to the entire class rather than an object.

静态方法、变量、块或嵌套类属于整个类,而不是对象。

A Method in Java is used to expose the behaviour of an Object / Class. Here, as the method is static (i.e, static method is used to represent the behaviour of a class only.) changing/ overriding the behaviour of entire class will violate the phenomenon of one of the fundamental pillar of Object oriented programming i.e, high cohesion. (remember a constructor is a special kind of method in Java.)

Java中的方法用于公开对象/类的行为。这里,由于方法是静态的(i。静态方法是用来表示类的行为的。)改变/覆盖整个类的行为将会违反面向对象编程i的基本支柱之一的现象。e,高内聚。(在Java中,构造函数是一种特殊的方法。)

High Cohesion - One class should have only one role. For example: A car class should produce only car objects and not bike, trucks, planes etc. But the Car class may have some features(behaviour) that belongs to itself only.

高内聚性——一个类应该只有一个角色。例如:汽车类应该只生产汽车对象,而不是自行车、卡车、飞机等。但是汽车类可能有一些属于自己的特性(行为)。

Therefore, while designing the java programming language. The language designers thought to allow developers to keep some behaviours of a class to itself only by making a method static in nature.

因此,在设计java编程语言时。语言设计者认为允许开发人员仅通过在本质上静态的方法来保持类的某些行为。


The below piece code tries to override the static method, but will not encounter any compilation error.

下面的代码尝试重写静态方法,但是不会遇到任何编译错误。

public class Vehicle {
static int VIN;

public static int getVehileNumber() {
    return VIN;
}}

class Car extends Vehicle {
static int carNumber;

public static int getVehileNumber() {
    return carNumber;
}}

This is because, here we are not overriding a method but we are just re-declaring it. Java allows re-declaration of a method (static/non-static).

这是因为,这里我们不是重写方法,而是重新声明它。Java允许重新声明方法(静态/非静态)。

Removing the static keyword from getVehileNumber() method of Car class will result into compilation error, Since, we are trying to change the functionality of static method which belongs to Vehicle class only.

从Car类的getVehileNumber()方法中删除静态关键字将导致编译错误,因为我们正在尝试改变静态方法的功能,而静态方法只属于Vehicle类。

Also, If the getVehileNumber() is declared as final then the code will not compile, Since the final keyword restricts the programmer from re-declaring the method.

另外,如果将getVehileNumber()声明为final,那么代码就不会编译,因为final关键字限制了程序员重新声明方法。

public static final int getVehileNumber() {
return VIN;     }

Overall, this is upto software designers for where to use the static methods. I personally prefer to use static methods to perform some actions without creating any instance of a class. Secondly, to hide the behaviour of a class from outside world.

总的来说,这是软件设计人员使用静态方法的原因。我个人倾向于使用静态方法来执行一些操作,而不需要创建类的任何实例。其次,隐藏来自外部世界的行为。

#21


-1  

Now seeing above answers everyone knows that we can't override static methods, but one should not misunderstood about the concept of accessing static methods from subclass.

现在看到上面的答案,每个人都知道我们不能重写静态方法,但是我们不应该误解从子类访问静态方法的概念。

We can access static methods of super class with subclass reference if this static method has not been hidden by new static method defined in sub class.

如果静态方法没有被子类中定义的新静态方法隐藏,那么我们可以使用子类引用来访问超类的静态方法。

For Example, see below code:-

例如,参见下面的代码:-。

public class StaticMethodsHiding {
    public static void main(String[] args) {
        SubClass.hello();
    }
}


class SuperClass {
    static void hello(){
        System.out.println("SuperClass saying Hello");
    }
}


class SubClass extends SuperClass {
    // static void hello() {
    // System.out.println("SubClass Hello");
    // }
}

Output:-

输出:

SuperClass saying Hello

See Java oracle docs and search for What You Can Do in a Subclass for details about hiding of static methods in sub class.

请参阅Java oracle文档,并在子类中搜索您可以在子类中做什么,以了解在子类中隐藏静态方法的细节。

Thanks

谢谢

#22


-3  

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

}   

}