最近在学习JAVA,看到书中有说:可以将子类的对象赋给父类的引用,但是在运行时,通过RTTI来判断引用所代表的是子类的对象还是父类的对象,并且能够正确地识别所调用的方法。那么按照这样的理解,下面的代码:
class A {
public boolean flag = false;
public void Show() {
System.out.println("From A");
}
}class B extends A {
public boolean flag = true;
public void Show() {
System.out.println("From B");
}
}public class Test {
public static void main(String[] args) {
A a = new A();
B b = new B();
A c = b;
System.out.println(a.flag);
System.out.println(b.flag);
System.out.println(c.flag);
a.Show();
b.Show();
c.Show();
}
}
这个代码的运行结果应该是:
false
true
true
From A
From B
From B
可是在实际的运行结果却是:
false
true
false
From A
From B
From B
请问这个是什么原因呢。
class A {
public boolean flag = false;
public void Show() {
System.out.println("From A");
}
}class B extends A {
public boolean flag = true;
public void Show() {
System.out.println("From B");
}
}public class Test {
public static void main(String[] args) {
A a = new A();
B b = new B();
A c = b;
System.out.println(a.flag);
System.out.println(b.flag);
System.out.println(c.flag);
a.Show();
b.Show();
c.Show();
}
}
这个代码的运行结果应该是:
false
true
true
From A
From B
From B
可是在实际的运行结果却是:
false
true
false
From A
From B
From B
请问这个是什么原因呢。
方法的问题就是根据你开头那段话来确定的.
field没有这个问题.
public boolean flag = false; public void Show() {
System.out.println("From A");
}
public boolean getflag(){
return flag;
}
}class B extends A {
public boolean flag = true; public void Show() {
System.out.println("From B");
}
public boolean getflag(){
return flag;
}
public boolean getsuperflag(){
return super.flag;
}
}public class test {
public static void main(String[] args) {
A a = new A();
B b = new B();
A c = new B(); System.out.println("*******************flag*********************");
System.out.println(a.flag);
System.out.println(b.flag);
System.out.println(c.flag);
System.out.println("*****************getflag()******************");
System.out.println(a.getflag());
System.out.println(b.flag);
System.out.println(c.getflag());
// System.out.println(c.getsuperflag()); a.Show();
b.Show();
c.Show();
}
}
我把楼主的代码改了一下,当我要加上System.out.println(c.getsuperflag());这句话时提示 A型没有定义。
说明实例c虽然是通过B创建的但C还是A类型。而且类继承时如果有相同名变量,子类中不会被覆盖,只是在子类中加super.
像楼主那样定义,用c.flag进行调用时,其实是调用A的flag
这是我的理解,有些词可能用的不对,我只是想表达个意思。请见谅
*******************flag*********************
false
true
false
*****************getflag()******************
false
true
true
From A
From B
From B这里我注意到:如果我直接去引用字段的话,如c.flag。则显示的是 false,若我去引用方法的话,如 c.getflag()。则显示的是true。这里的一个区别是:一个是引用所代表的类型的值,一个是赋给引用的对象的类型的值。这个是关键点。就是说为什么字段和方法的覆盖会不同呢?
class A {
public boolean flag = false;
public void Show() {
System.out.println("From A");
}
public boolean flagChange(){
return flag;
}
} class B extends A {
public boolean flag = true;
public void Show() {
System.out.println("From B");
}
public boolean flagChange(){
return this.flag;
}
} public class Test {
public static void main(String[] args) {
A a = new A();
B b = new B();
A c = new B();
System.out.println(a.flag);
System.out.println(b.flag);
System.out.println(c.flag);
System.out.println(c.flagChange());
a.Show();
b.Show();
c.Show();
}
} /* output:false
true
false
true
From A
From B
From B
B类
{
public boolean super.flag = false; //A
public boolean flag = ture; //B
public void Show() {
System.out.println("From B");
}
public boolean getflag(){
return flag;
}
public boolean getsuperflag(){
return super.flag;
}
}c是A类型,当c用B去创建时 c.flag 应该是 super.flag
getflag()被重写了 c.getflag() 应该是 flag
不知道你看懂了吗?我表达可能不清。
c
{
public boolean super.flag = false; //A
public void Show() {
System.out.println("From B");
}
public boolean getflag(){
return flag; //B中flag
}
}
在上溯的过程中,接口变窄了,它本身的一些方法(例 getsuperflag())就不可见了。
1:当父引用(装子对象).子类独有方法 ---------------编译错误 因为javac 时,JVM会先检查你父类有无此方法,如果 没有就报错,而后考虑父引用装的是不是子对象2:当父引用(装子对象).子类重写父member方法 --------这时调的是子类的重写方法。
3:当父引用(装子对象).子类重写父static方法 --------这时调的是父类的方法。
3:当父引用(装子对象).属性(不管static和member属性) --------这时调的是父类的属性。
不是声明c是A类吗 ,A c = b————只是说明给c赋初值,即给定一个存储地址,但c作为一个A类其方法和变量都不变。
java中有两种绑定,静态绑定和动态绑定。变量用的是静态绑定,就是说在编译的时候已经绑定好了。而方法是在运行时去绑定的。换句话说就是在.java文件编译成.class文件的时候变量的值已经定死了。所以sup.field等于0。
静态绑定:变量和静态方法。
动态绑定:实例方法。