package tao.integer; class Base{ public String str = "base"; public Base(){ System.out.println("cons: base... "+this);// cons: base... tao.integer.Sub@1fb8ee3 this.func(); // func: sub ..... System.out.println(this.str);// base } public void func(){ System.out.println("func: base ....."); } } class Sub extends Base{ public String str = "Sub"; public Sub(){ // System.out.println("cons: sub... "+this); // System.out.println(this.str); } public void func(){ System.out.println("func: sub ....."); } } public class Demo { public static void main(String[] args) { // Base base = new Base(); // base.func(); // System.out.println(base.str); // // System.out.println("//////////////"); // Sub sub = new Sub(); // sub.func(); // System.out.println(sub.str); System.out.println("//////////////"); Base base2 = new Sub(); // base2.func(); // System.out.println(base2.str); } }
网友回复:
============
System.out.println("cons: base... "+this); //cons: base...Sub@1fb8ee3
// this 指向的是子类 Sub
this.func(); // func: sub .....
System.out.println(this.str); //不懂???为啥输出 .... base
这里控制台下是输出base...Sub@1fb8ee3,但是这个this实际上是调用了toSting方法,而这个方法的调用是在运行时确定的。但是this.str这个又不一样了,这个调用的是字段,应该是在编译时确定的,也就是说这里的this.str在编译时确定为Base中的str。
按你的意思应该是说这个this.str应该指的是Sub的str。但是请看下面这段代码编译就都不能编译,
-
class BaseA
{
public BaseA()
{
System.out.println(this);
System.out.println(this.s);
}
}
class BaseB extends BaseA
{
public String s = "base";
public BaseB()
{
System.out.println(this);
System.out.println(this.s);
}
}
public class Test extends BaseB
{
public String s = "test";
public Test()
{
System.out.println(this);
System.out.println(this.s);
}
public static void main(String[] args)
{
Test t = new Test();
}
}
按你所写的意思好像是指this调用的字段,方法都应该在运行时刻确定,但是如果基类中不存在某个子类中的字段,这个时候编译不通过。那么这种情况作何解释,如果按照运行时来确定字段,那么这样的代码理论上讲就应该编译通过。java还不是那种动态到这种级别的语言吧。大部分情况下还是静态的,只有在方法调用的时候它才是动态的吧。
在父类Base中,看到的str是属于Base的str
在子类Sub中,默认调用的是str是属于Sub的str,但是可以用super.str取得父类Base的str
变量是不存在覆盖的,而是一个shadow,即父类子类的这个变量其实都是独立存在的,所以在父类中调用this.str仍然是base,不会被子类的sub覆盖掉