在一个扩展Java中另一个类的类中有两个具有相同名称的变量

以下是我的项目代码的一部分:

public class Body extends Point{ public double x, y, mass; public Body() { x = y = mass = 0; } public Body(double x, double y, double mass) { this.mass = mass; this.x = x; this.y = y; } } public class Point { public double x; public double y; public Point(double x, double y) { this.x = x; this.y = y; } } 

我很快意识到这样做会在Body类中创建两个名为x的变量,在Body中创建另外两个名为y的变量。 这怎么可能,以及为什么Java甚至允许它呢?

我假设这是类Body的正确代码:

 public class Body extends Point{ public double mass; public Body() { super(); mass = 0; } public Body(double x, double y, double mass) { super(x,y); this.mass = mass; } } 

谢谢你的时间

从某种意义上说,你是超越超级阶层的领域。 但是,由于没有字段的重载(你只有一个给定名称的变量,类型无关紧要),因此更容易意外地进行操作。 这被称为变量’隐藏’或’阴影’。 所以,你是对的,你最终会得到两个同名的字段。

你的第二个例子是正确的。 它们是从超类inheritance的,因为它们未被声明为私有,所以它们对子类是可见的。 直接引用超类的字段通常是不好的做法,除非有充分的理由,否则它们应该被声明为私有。 调用超级构造函数的示例是最好的方法。

此外,如果你隐藏一个具有相同名称的字段,你仍然可以将它们称为super.x,super.y,而不是this.x,this.y,如果可能的话,你应该避免这种情况。

是的,你将有两个变量,一个隐藏另一个。 允许它有两个原因:

  1. 假设你有一个基类Base和派生类DerivedBase的作者根本不知道。 Base的作者是否应该能够添加任何字段,只是因为派生类可能共享字段? 或者,当对Base的更改实际上不影响正确性时, Derived是否应该停止编译?
  2. 你的字段几乎总是私有的,此时名称是否重复并不重要 – “side”都不会知道另一个的变量。

继其他人所说的: Body是一个Point吗? 不, Body具有Point类型的位置属性。 所以Body可能不应该扩展Point 。 如果你摆脱inheritance(实现),那么你摆脱了很多问题。 那并且使用private (不受protected !)和final自由。

我很快意识到这样做会在Body类中创建两个名为x的变量,在Body中创建另外两个名为y的变量。 这怎么可能,以及为什么Java甚至允许它呢?

实际上不,你没有创建两个具有相同名称的变量,显然编译器不应该也不允许这样做。

正在做的是遮蔽定义为xy的现有变量,这意味着Body.x和Body.y基本上重叠了Point.x和Point.y的名称,使得后两个变量完全无法从Body类中访问( 链接到Java语言规范定义的“阴影” )。

名称阴影通常被认为是一种不良做法和错误原因,如果你打开javac编译器警告,编译器将尽职尽责地警告你。