当前位置: 首页 > 面试题库 >

具有实例变量的多态[重复]

林正平
2023-03-14
问题内容

这是我写的三个类:

public class Shape {

    public int x = 0;

    public void getArea() {
        System.out.println("I don't know my area!");
    }

    public String toString() {
        return "I am a shape!";
    }

    public int getX() {
        return x;
    }
}

public class Rectangle extends Shape {

    public int x = 1;

    public int getX() {
        return x;
    }

    public void getArea() {
        System.out.println("L*W");
    }

    public String toString() {
        return "I am a rectangle!";
    }
}

public class Tester {

    public static void main(String[] args) {
        Shape s = new Shape();
        Rectangle r = new Rectangle();

        System.out.println(r);
        System.out.println(r.x + "\n");

        s = r;
        System.out.println(s);
        s.getArea();
        System.out.println(s.x);
        System.out.println(s.getX());
    }
}

Tester类的main方法的输出为:

我是矩形!

1个

我是矩形!

长*宽

0

1个

为什么sx返回0而不是1?由于不是Rectangle变量的当前实例,并且该类也声明了相同的实例变量,或者Rectangle类中的变量没有像对getX()一样覆盖Shape类中的先前公共x变量。矩形类中的方法因此返回1?

同样作为一般规则,超类仅在其子类中也声明了其子类方法时才可以访问其子类的实现?这是因为编译器会看到“
Shape”类(具有重写的Rectangle实现)中有相同数量的具有相同签名的方法,并将它们接受为有效的Shape方法吗?

提前致谢,


问题答案:

Java中的字段没有多态性。但是,有继承。有效完成的工作是在Rectangle类中创建两个名称相同的字段。该字段的名称实际上是:

public class Rectangle {
    public int Shape.x;
    public int Rectangle.x;
}

上面的代码并不代表有效的Java,它只是说明如何在类中定义字段的范围

在Rectangle类的整个范围内,同名的超类字段被 隐藏
。因此,无论何时在类中引用简单名称x或范围名称this.x,都将引用中定义的字段Rectangle。实际上,您还可以使用作用域名称来访问超类字段super.x

现在,从类外部,正在访问其字段的规则略有不同。范围将由引用该字段的类的 编译 时间类型确定。因此,在您的代码中:

Shape s = new Shape();
Rectangle r = new Rectangle();

s = r;
System.out.println(s.x);

输出是0因为的编译时间类型sShape(not Rectangle)。当您这样做时,您可以观察到此行为的变化:

Shape s = new Shape();
Rectangle r = new Rectangle();

s = r;
System.out.println(((Rectangle)s).x);

快点!现在的输出是1,因为编译器看到您已将域访问范围限定为Rectangle

浓缩可见性规则:

您可以在JLS的8.3.3.2节中阅读有关隐藏实例变量的更多信息。



 类似资料:
  • 问题内容: 我有一个无状态会话bean,其中包含一个公共方法,几个私有方法和一些实例级变量。下面是一个伪代码示例。 我看到的是methodB正在打印未传递给MethodA的值。最好的说来,它是从同一bean的其他实例打印值。是什么原因造成的? 我应该指出代码在99.9%的时间内都能正常工作。但是,.01%对我造成了一些严重的问题/担忧。 我知道,如果我使用不同的公共方法,则两次调用之间可能无法获得

  • 问题内容: 静态变量只有实例(也就是说,它们是类的一部分)。例如:Math.pi 有什么办法可以有多个静态变量实例吗?我听说有一些与Classloader相关的东西吗? 问题答案: 如果发现需要一个静态变量的多个实例,则强烈表明您不应该首先使用静态变量。 是的,如果同一类加载到不同的类加载器中,则该类的每个副本将具有其自己的静态变量。但是,唯一可以静态引用这些静态变量的代码将是由同一类加载器加载的

  • 所以我正在研究一个现有的模拟器软件,其结构基本上是这样的(它有一个静态成员变量包含它自己):

  • 静态变量和实例变量之间的区别是什么。下面这句话是我无法理解的: 在某些情况下,一个类的所有对象只能共享一个特定变量的副本——这里使用静态变量。 静态变量代表类范围的信息。一个类的所有对象共享相同的数据。 我认为实例变量在类范围内使用,而静态变量只在它们自己的方法中有作用域?

  • 问题内容: 我刚刚开始使用Sass和Compass,我喜欢它。我想做的就是利用该功能简化重复性任务。但是,我仅看到了插入一个变量的示例,并且我希望能够使用多个变量。 标准方式(来自[Sass参考): 很棒,但是我希望能够执行以下操作: 这可能吗? 问题答案: 我在同一条船上(Sass / Compass的初学者),不得不做类似的事情。这是我使用嵌套列表想到的: 这不是最优雅的解决方案,但是如果您找

  • 问题内容: 在react.js中,将超时引用存储为实例变量(this.timeout)或状态变量(this.state.timeout)更好吗? 要么 这两种方法都有效。我只想知道一个使用另一个的原因。 问题答案: 我建议将其存储在实例上,而不是存储在实例中。每当更新时(应仅按注释中的建议完成),React就会调用并对实际DOM进行任何必要的更改。 由于的值对组件的呈现没有影响,因此不应存在于中。