当我拥有A类和B扩展了A的B类并且它们具有公共实例变量大小并且下面的命令从B内部的printSize1方法调用时,这些命令之间有什么区别?

class A {
    protected int size;
}

class B extends A {
    protected int size=7;

    public void printSize1() {
        System.out.println(((A)this).size)
        System.out.println(super.size);
    }
}


我对这两个也有同样的问题。我有一个类A和一个类B,其中B扩展了A,并且它们都具有一个具有相同名称printSize和一个实例变量size的方法,并且下面的命令是从类B内部的方法printSize2调用的。

class A {
    protected int size;

    public void printSize() {
        System.out.println("Size=" + size);
    }
}

class B extends A {
    protected int size=7;

    public void printSize2 {
        ((A) this).printSize();
        super.printSize();
    }

    public void printSize() {
       System.out.println ("MSize="+size);
    }
}

最佳答案

我有一个A类和一个B类,其中B扩展了A,它们具有相同的实例变量大小


不,他们没有。它们具有称为size的单独的实例变量。一个在与A关联的对象部分中,另一个在与B关联的对象部分中。让我们将它们称为A$sizeB$size。为了使它们具有公共实例变量,请从size中删除​​B的声明,以便它们都使用A$size

重新声明祖先的非private实例变量(字段)总是一个坏主意,因为这会导致这种混乱。

下面的两个示例代码输出0,因为它们都在访问A$size,而您从未为其分配值,因此默认值为0

System.out.println(((A)this).size);  // 0
System.out.println(super.size);      // 0


所以问题是:为什么他们都使用A$size而不是B$size?由于引用的类型,我们用来查找size。在这两种情况下,引用的类型均为A,因为(A)this的类型为A(通过强制转换),并且super中的方法中的B的类型也为A。由于引用的类型为A,因此将使用Asize

在这种特殊情况下,两者之间没有太大的区别,但是如果您向层次结构中添加了另一层,那就会有很大的区别:

class A {
    protected int size = 1;
}
class B extends A {
    protected int size = 2;
}
class C extends B {
    protected int size = 3;

    void printSize() {
        System.out.println(((A)this).size);  // 1
        System.out.println(super.size);      // 2
        System.out.println(this.size);       // 3
    }
}


故事的寓意:不要重新声明由祖先声明的实例变量(除非祖先的版本为private)。

请注意,变量与方法不同。实例方法是多态的。实例变量不是。使用方法,您可以获得与对象的最终类型关联的方法(除非您使用super或合格的super,因为它们是特殊的并且绕过了多态性)。

这就是您在printSize2的第二个示例中所要发挥的作用。因为方法是多态的,所以不必将this强制转换为A中的((A)this).printSize()类型,仍然会得到BprintSize。但是super.printSize()是特殊的,因为super是特殊的,并且绕过了多态性,使B可以访问AprintSize

关于java - 在下面的命令中,super和this之间的区别?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42876391/

10-12 03:13