以下是代码,
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
,如果this
指向T3
类型的对象。
那么,现场访问遵循的规则背后的理由是什么?例如,规则方法对我有意义。
注意:对我来说,除非有正当理由,否则记住这些规则是一种开销。
答案 0 :(得分:2)
通过V-table解析实例方法,即调用运行时类型的方法。没有这样的表为字段(或静态方法)启用此功能,因此使用编译时类型。
隐藏字段然后做这种事((T1)this).x
非常不寻常,我会避免它,因为我认为它不可读。
java docs确认:
在一个类中,与超类中的字段同名的字段会隐藏超类的字段,即使它们的类型不同。在子类中,超类中的字段不能通过其简单名称引用。相反,必须通过super访问该字段,这将在下一节中介绍。 一般来说,我们不建议隐藏字段,因为它会使代码难以阅读。
(强调我的)
因此,要记住的规则列表应该很低。
你可以在所有好的IDE中打开错误/警告,这里是IntelliJ:
答案 1 :(得分:1)
将拇指规则保持为:
考虑下面的例子:
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