java 为什么继承类静态方法而不是接口静态方法?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25169175/
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
Why are class static methods inherited but not interface static methods?
提问by Radon Rosborough
I understand that in Java static methods are inherited just like instance methods, with the difference that when they are redeclared, the parent implementations are hidden rather than overridden. Fine, this makes sense. However, the Java tutorialnotes that
我知道在 Java 中静态方法就像实例方法一样被继承,区别在于当它们被重新声明时,父实现被隐藏而不是被覆盖。好吧,这是有道理的。但是,Java 教程指出
Static methods in interfaces are never inherited.
接口中的静态方法永远不会被继承。
Why? What's the difference between regular and interface static methods?
为什么?常规和接口静态方法有什么区别?
Let me clarify what I mean when I say static methods can be inherited:
当我说静态方法可以被继承时,让我澄清一下我的意思:
class Animal {
public static void identify() {
System.out.println("This is an animal");
}
}
class Cat extends Animal {}
public static void main(String[] args) {
Animal.identify();
Cat.identify(); // This compiles, even though it is not redefined in Cat.
}
However,
然而,
interface Animal {
public static void identify() {
System.out.println("This is an animal");
}
}
class Cat implements Animal {}
public static void main(String[] args) {
Animal.identify();
Cat.identify(); // This does not compile, because interface static methods do not inherit. (Why?)
}
采纳答案by agbinfo
Here's my guess.
这是我的猜测。
Since Cat
can only extend one class if Cat
extendsAnimal
then Cat.identify
has only one meaning. Cat
can implementmultiple interfaces each of which can have a static implementation. Therefore, the compiler would not know which one to choose?
由于Cat
只能扩展一个类,如果Cat
扩展Animal
则Cat.identify
只有一种含义。Cat
可以实现多个接口,每个接口都可以有一个静态实现。因此,编译器不知道该选择哪一个?
However, as pointed out by the author,
然而,正如作者所指出的,
Java already has this problem, with default methods. If two interfaces declare default void identify(), which one is used? It's a compile error, and you have to implement an overriding method (which could just be Animal.super.identify()). So Java already resolves this problem for default methods – why not for static methods?
Java 已经有这个问题了,默认方法。如果两个接口都声明了默认的 void identify(),那么使用哪一个?这是一个编译错误,您必须实现一个覆盖方法(可能只是 Animal.super.identify())。所以Java已经为默认方法解决了这个问题——为什么不是静态方法呢?
If I was to guess again, I'd say that with default
the implementation is part of Cat
's vtable. With static
it cannot be. The main function must bind to something. At compile time Cat.identify
could be replaced with Animal.identify
by the compiler but the code wouldn't match reality if Cat
was recompiled but not the class that contains main.
如果我再猜一次,我会说default
实现是Cat
vtable 的一部分。有了static
它不能。main 函数必须绑定到某些东西。在编译时Cat.identify
可以被Animal.identify
编译器替换,但是如果Cat
重新编译而不是包含 main 的类,代码将与现实不符。
回答by But I'm Not A Wrapper Class
Before Java 8, you couldn't define static
methods in an interface
. This is heavily discussed in this question. I'm going to refer to this answer(by user @JamesA.Rosen) as to why the Java designers probably didn't want static
methods in an interface
initially:
在Java 8之前,您不能static
在interface
. 这在这个问题中有大量讨论。我将参考这个答案(由用户@JamesA.Rosen 提供)来解释为什么 Java 设计者最初可能不想要static
方法interface
:
There are a few issues at play here. The first is the issue of declaring a static method without defining it. This is the difference between
这里有几个问题。第一个是声明一个静态方法而不定义它的问题。这是之间的区别
public interface Foo {
public static int bar();
}
and
和
public interface Foo {
public static int bar() {
...
}
}
Java doesn't allow either, but it could allow the second. The first is impossible for the reasons that Espo mentions: you don't know which implementing class is the correct definition.
Java could allow the latter, as long as it treated Interfaces as first-class Objects. Ruby's Modules, which are approximately equivalent to Java's Interfaces, allow exactly that:
Java 不允许,但它可以允许第二个。由于 Espo 提到的原因,第一个是不可能的:您不知道哪个实现类是正确的定义。
Java 可以允许后者,只要它将接口视为一流的对象。Ruby 的模块,大致相当于 Java 的接口,完全允许:
module Foo
def self.bar
...
end
end
However, since the release of Java 8, you can actually add default
and static
methods inside an interface
.
然而,由于发布的Java 8,实际上你可以添加default
和static
内部的方法interface
。
I'm going to be quoting this sourcea lot here. This is the initial problem:
我将在这里大量引用这个来源。这是最初的问题:
Java's interface language feature lets you declare interfaces with abstract methods and provide implementations of those methods in the classes that implement the interfaces. You are required to implement each method, which is burdensome when there are many methods to implement. Also, after publishing the interface you cannot add new abstract methods to it without breaking source and binary compatibility.
Java 的接口语言特性允许您使用抽象方法声明接口,并在实现接口的类中提供这些方法的实现。每个方法都需要你去实现,当要实现的方法很多时,这很麻烦。此外,发布接口后,您无法在不破坏源代码和二进制兼容性的情况下向其添加新的抽象方法。
This was the solution Java 8provided default
:
这是Java 8提供的解决方案default
:
Java 8 addresses these problems by evolving the interface to support default and static methods. A default method is an instance method defined in an interface whose method header begins with the default keyword; it also provides a code body. Every class that implements the interface inherits the interface's default methods and can override them
Java 8 通过改进接口以支持默认和静态方法来解决这些问题。默认方法是在接口中定义的实例方法,其方法头以 default 关键字开头;它还提供了一个代码体。每个实现接口的类都继承接口的默认方法并且可以覆盖它们
And for static
:
而对于static
:
A static method is a method that's associated with the class in which it's defined, rather than with any object created from that class. Every instance of the class shares the static methods of the class. Java 8 also lets static methods be defined in interfaces where they can assist default methods.
When you implement an interface that contains a static method, the static method is still part of the interface and not part of the implementing class. For this reason, you cannot prefix the method with the class name. Instead, you must prefix the method with the interface name
静态方法是与定义它的类相关联的方法,而不是与从该类创建的任何对象相关联的方法。类的每个实例共享类的静态方法。Java 8 还允许在接口中定义静态方法,它们可以辅助默认方法。
当你实现一个包含静态方法的接口时,静态方法仍然是接口的一部分,而不是实现类的一部分。因此,您不能使用类名作为方法的前缀。相反,您必须使用接口名称作为方法的前缀
Example:
例子:
interface X
{
static void foo()
{
System.out.println("foo");
}
}
class Y implements X
{
}
public class Z
{
public static void main(String[] args)
{
X.foo();
// Y.foo(); // won't compile
}
}
Expression
Y.foo()
will not compile becausefoo()
is a static member of interfaceX
and not a static member of classY
.
表达式
Y.foo()
不会编译,因为它foo()
是 interface 的静态成员,X
而不是 class 的静态成员Y
。
回答by Styl
Static methods in interfaces could create a diamond of death if they were being inherited. So, calling a static method from the appropriate interface is good enough compared to the risk of calling it from a concrete class that may implement multiple interfaces that contain static methods of the same name.
如果接口中的静态方法被继承,它们可能会造成死亡钻石。因此,与从可能实现多个包含同名静态方法的接口的具体类中调用静态方法的风险相比,从适当的接口调用静态方法就足够了。
Why are static methods any different?
为什么静态方法有什么不同?
Static methods are just functions unrelated to the objects. Instead of placing them in utility abstract classes (like calling Collections.sort() ) we move those functions (static methods) to their appropriate interfaces. They could be bound to the inherited objects like the default methods do, but that is not their job. Static methods provide functionality which is unrelated to the instances of the class.
静态方法只是与对象无关的函数。我们没有将它们放在实用程序抽象类中(比如调用 Collections.sort() ),而是将这些函数(静态方法)移动到它们适当的接口中。它们可以像默认方法一样绑定到继承的对象,但这不是它们的工作。静态方法提供与类的实例无关的功能。
Example:
例子:
interface Floatable {
default void float() {
// implementation
}
static boolean checkIfItCanFloat(Object fl) {
// some physics here
}
}
class Duck implements Floatable { }
So, the point is that a Duck may float but the function that checks if an Object really floats is not something that a Duck can do. It is an irrelevant functionallity that we could pass to our Floatable interface instead of having it sit inside some utility class.
所以,关键是鸭子可以漂浮,但检查对象是否真的漂浮的函数不是鸭子可以做的。这是一个无关紧要的功能,我们可以将其传递给我们的 Floatable 接口,而不是让它位于某个实用程序类中。
回答by Benjamin Curtis Drake
Let's begin with some background ...
让我们从一些背景开始......
Java doesn't support multiple inheritance (the ability to extend more than one class). This is because multiple inheritance is prone to the deadly diamond of death (also known as the diamond problem) which the designers of Java chose to preempt.
Java 不支持多重继承(扩展多个类的能力)。这是因为多重继承容易出现 Java 设计者选择抢占的致命的死亡钻石(也称为钻石问题)。
If B and C override a method inherited from A, which method does D inherit?
如果 B 和 C 重写了从 A 继承的方法,那么 D 继承了哪个方法?
A class can implement multiple interfacesbecause interface methods are contracted for overriding; if a class C implements two interfaces A and B that declare the same method, then the same method in C will be invoked by clients of either interface (A or B). The introduction of default methods for interfaces in Java 8 was made possible by forcing the implementer to override the default in case of ambiguity. This was an acceptable compromise since default methods are intended to be defensive(to be used if no other implementation is explicitly provided by an implementer). However, since the compiler can't force you to override a static method (static methods inherently can't be overridden), the introduction of static methods for interfaces in Java came with one restriction: the static methods of an interface are not inherited.
一个类可以实现多个接口,因为接口方法是为了重写而约定的;如果类 C 实现了两个声明相同方法的接口 A 和 B,则 C 中的相同方法将被任一接口(A 或 B)的客户端调用。在 Java 8 中为接口引入默认方法是通过强制实现者在出现歧义时覆盖默认值而成为可能的。这是一个可以接受的折衷方案,因为默认方法是防御性的(如果实现者没有明确提供其他实现,则使用)。但是,由于编译器无法强制您覆盖静态方法(静态方法本质上不能被覆盖),因此 Java 中为接口引入静态方法有一个限制:接口的静态方法不是继承的。