下面是代码,

package ClassesOverridingHidingAccess;

interface I{
    int x = 0;
}
class T1 implements I{
    int x = 1;
    String s(){
        return "1";
    }
}

class T2 extends T1{
    int x  = 2;
    String s(){
        return "2";
    }
}

class T3 extends T2{
    int x = 3;
    String s(){
        return "3";
    }

    void test(){
        // Accessing instanc method
        System.out.println("s()=\t\t" + s());   // 3
        System.out.println("super.s()=\t" + super.s()); // 2
        System.out.println("((T2)this).s()= " + ((T2)this).s());  // 3; method is resolved at runtime
        System.out.println("((T1)this).s()= " + ((T1)this).s());  // 3; method is resolved at runtime

        //Accessing instance attribute
        System.out.println("\n\nx=\t\t" + x);  // 3
        System.out.println("super.x=\t" + super.x);  // 2
        System.out.println("((T2)this).x=\t" + ((T2)this).x);  // 2; resolved at compile time
        System.out.println("((T1)this).x=\t" + ((T1)this).x);  // 1; resolved at compile time
        System.out.println("((I)this).x=\t" + ((I)this).x);   // 0; resolved at compile time
    }
}

public class SuperAndInstanceMethods {
    public static void main(String[] args) {
        (new T3()).test();
    }
}


哪里,

它是运行时类,在访问实例方法时进行计数。

它是对象的视图,在进行字段访问时很重要。

强制转换不会更改对象的类类型。我的意思是,如果((T1)this) instanceof T3指向类型为true的对象,则thisT3

那么,现场访问所遵循的规则背后的原理是什么?实例方法的规则对我来说很有意义。

注意:对我来说,除非有适当的理由,否则记住这些规则是一项开销。

最佳答案

实例方法是通过V-table解析的,这就是调用运行时类型的方法的方式。没有这样的表可以为字段(或静态方法)启用此功能,因此使用了编译时类型。

隐藏字段然后执行此类操作((T1)this).x是非常不寻常的,我会避免使用它,因为我认为它不可读。

并且java docs确认:


  在一个类中,与超类中的字段同名的字段会隐藏超类的字段,即使它们的类型不同。在子类中,无法通过其简单名称引用超类中的字段。相反,必须通过super访问该字段,这将在下一部分中介绍。一般来说,我们不建议隐藏字段,因为这会使代码难以阅读。


(强调我的)

因此,要记住的规则列表应该很少。

您可以在所有好的IDE中为此打开错误/警告,这在IntelliJ中:

java - 实例方法覆盖vs字段隐藏-LMLPHP

07-28 03:57
查看更多