2

下面是代码,

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 T3true,如果this指向对象类型T3

那么,字段访问遵循的规则背后的基本原理是什么?规则例如方法对我来说很有意义。

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

4

2 回答 2

2

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

隐藏字段然后做这种事情((T1)this).x是非常不寻常的,我会避免它,因为我认为它不可读。

Java 文档确认:

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

(强调我的)

所以它应该在你要记住的规则列表中很低。

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

智能检测

于 2015-07-27T07:51:19.780 回答
1

保持拇指规则为:

  1. 在方法覆盖的情况下,引用变量无关紧要,但重要的是该变量所引用的实际对象类型。
  2. 在变量阴影/字段隐藏的情况下,引用变量很重要,而该变量所引用的实际对象类型无关紧要。

考虑以下示例:

public class Parent {
    String name = "Parent";
    public void printName(){
    System.out.println("Parent Method");
  }
}

public class Child extends Parent {
  String name = "Child";
  public void printName(){
    System.out.println("Child Method");
   }
}

现在将在测试类main()中运行此方法:-

public class Test {

public static void main(String[] args) {
    Parent p = new Parent();
    Child c = new Child();

    System.out.println(p.name); // will print Parent's name
    System.out.println(p.printName());// will call Parent
    System.out.println(c.name); // will print Child's name
    System.out.println(c.printName());// will call Child

    Parent pc = new Child();
    System.out.println(pc.name);// will print Parent's name
    System.out.println(pc.printName());// will call Child
   }
}

这将根据我上面所说的规则打印以下内容:-

Parent 
Parent Method
Child
Child Method
Parent
Child Method
于 2015-07-27T07:43:58.843 回答