繁体   English   中英

类、接口和实现接口的类中方法的覆盖、重新声明、隐藏和重新定义

[英]Overriding, redeclaring, hiding and redefining of methods in classes, interfaces and classes implementing interfaces

Would it be correct to say that static methods in a class extended with a class, in an interface extended with an interface and in an interface implemented by a class can only be redeclared in the extending/implementing part (hiding the original method), and任何其他方法只能在那里被覆盖? 重新定义与覆盖相同吗?

如果没有,有人可以用流程图解释这些概念吗(我看过其他解释,他们没有给我我正在寻找的概述)?

说 static 方法在 class 扩展中是否正确

No. static 方法基本上是不可继承的,不可覆盖的。 或者更确切地说,从概念上讲,它只是不适用。

说:“这个 static 方法是一种替代方法”有点像说:“这闻起来很蓝”——甚至不清楚这意味着什么。

覆盖本质上只与动态调度的概念有关。 动态调度是这样的想法:

class Dog {
  void bark() { System.out.println("Woof"); }
}

class Bulldog extends Dog {
  void bark() { System.out.println("Grrrr"); }
}

Dog d = new Bulldog();
d.bark(); // prints "Grrrr"

这就是工作中的动态调度。 d是一个变量。 像 java 中的所有非基元一样,它是一个参考 意思是,存储在此变量中的值是引用- 一个指针。 地址簿中的地址,可让您到达房子,而不是房子本身。 d的类型是Dog 它的值是对某些 object 的实际实例的引用(并且 java 保证无论它是一个实例的实际类型,该类型是DogDog的子类型)。 该引用为您提供了Bulldog的实例。 那么,在这里调用bark()时,会发生什么?

动态调度:Java 找到该方法最具体的实现,并调用. 这样打印Grrrr ,而不是Woof

然而,当谈到 static 方法时,整个概念并不适用。 发生动态调度是因为引用的类型(这里是Dog ,即变量d的类型)和引用指向的事物的类型(即Bulldog )之间存在差异。 覆盖作为一个概念存在是因为这两种类型可能不同。

调用 static 方法时,这不会出现 你总是写SomeType.someStaticMethod() ,那么动态调度甚至是什么?

旁注:您可以使用表达式合法地调用 static 方法。 这是合法的:

List.of("a", "b"); // this is how you normally do it
List<Integer> list = new ArrayList<Integer>();
list.of("a", "b"); // this compiles and works

但不要搞错 - 编译器对待它是一样的,关心list的类型,而不关心变量指向的 object 。 事实上, list = null; list.of("a", "b"); list = null; list.of("a", "b"); 工作正常,没有 NullPointerException,证明这样做时list不会被取消引用。 所有风格指南都强烈建议不要这样做,这是有充分理由的。

旁注2:不幸的是,java 允许您将 static 方法声明为final ,这很奇怪: final意味着:不能被覆盖,我们刚刚发现“覆盖”在概念上对 ZA821259CEF456E959 方法没有意义。 就是这样 - 这是原始 java 规范和 java 中的设计错误,除非有非常好的理由这样做,否则不喜欢进行破坏现有代码的更改,虽然这个规范很烦人,但它不会伤害很多。 只是不要将您的 static 方法声明为final 它甚至添加了一个更奇怪的规则(子类型不能声明具有相同签名的 static 方法)。 再次,无视这一点 - java 规范错误没有得到修复,因为不值得头疼。

重新定义与覆盖相同吗?

是的。 2个词代表同一件事。 正确的术语是“覆盖”——java 语言规范都使用这个术语,社区中的绝大多数人都这样做。 如果我是任何教程、博客文章、文档或演示文稿的编辑,你会得到这个“重新定义”的术语,我会编辑它。 除非作者特意讲这个:

class Parent {
  static void foo() {}
}

class Child extends Parent {
  static void foo() {}
}

在这种情况下,“覆盖”是使用错误的术语(鉴于 static 方法和覆盖是正交概念),尽管我也不会使用“重新定义”。 您只是在一个 class 中定义了一个名为foo的方法,还在另一个 class 中定义了一个名为foo的方法。 一个是另一个孩子的事实是无关紧要的。 现在两者都有一个foo方法。 child 中的 foo 方法不会覆盖或重新定义任何东西; static世界中没有这样的东西。

有流程图

流程图需要某种流程图来绘制。 由此得名。 这里没有这样的东西。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM