class A{
public char i = 'a';//----------------------------------1
public void start(){
System.out.println("A is started!" + i);
}
}
class B extends A{
public char i = 'b';//----------------------------------2
public void start(){
System.out.println("B is started!"+ super.i);
}
public void jump(){
System.out.println("B is jumping!"+ i);
}
}public class Test1{
public static void main(String[] args){
A a = new A();
a.start();
B b = new B();
b.start(); 
A ab = new B();
ab.start();//---------------------------------------3
//ab.jump();//--------------------------------------4 }
}输出结果:
A is started!a
B is started!b
B is started!b问题1:在注释1和注释2处,为什么编译时没有提示“重复定义”?在一本java书上的原话如此:“我们不可以在子类中重新定义继承得到的成员的访问属性。如果我们试图重新定义一个 在父类中已经存在的私有成员变量,那么我们是在定义一个与父类的而成员变量完全无关的变量,在子类中我们可以访问这个定义在子类中的变量,在父类的方法中访问父类的那个,尽管他们同名但互不影响。如果我们试图定义一个父类中已经能够存在的非私有成员变量,编译器会提示给我们一个编译错误。”实践结果好像和上述论述不符。问题2:注释4处,如果取消注释,就会有编译错误:“A类没有方法jump().”这样就牵扯出向上类型转换中的一个问题,如上面的程序,对象ab,我看到网上有一段论述说,ab这样的对象,“占有B类对象那么大的内存,拥有B对象的方法,拥有A对象的属性”。从上面的实践可以看出:ab.i应该是‘b’,而ab.start()也是B类的方法(由注释3处可以看出)。但是ab.start()是不存在的。这样的结果与上述的论述不符。请教解释。我的推断是:ab这样的对象,还拥有A类对象那么大的内存,也拥有A类对象的方法和属性,但是这些方法和属性如果在B类中被重写过或者重新定义过,ab对象中的属性和方法也就更新了。如果在B类中没有重写过,则肯定还是原来A中的方法和属性。但是B类中新增的方法和属性,并不会加到ab中,因为ab的大小是和A类对象的大小一样的,没有地方容纳新增的东西。不知道这样的总结对不对?请各路高手不吝赐教!

解决方案 »

  1.   

    问题1,不知道你看的什么书,很可笑的书。对于方法,有这样的说法,如果父类定义了private的方法,子类再定义一个相同的private方法的话,这两个方法没什么关系,不存在override关系。static方法也不存在override关系。final方法不允许override。其他的方法,子类可以overrride父类的方法(签名相同),这也是多态的关键。
    问题2,编译器找方法的时候是根据类型来的, A ab = new B();ab这个引用的类型是A,A中没有方法jump();所以不允许ab.jump
      

  2.   

    关于对象大小的说法也头一次见。
    起码先知道ab,a,b这三个只是引用,不是对象。
      

  3.   


    在书里这段论述里,说的是子类中重定义父类的属性(数据成员),没有说方法(函数成员)。我想知道,明明A类中的public的i被B类继承下来了,再B中再重新定义public的i,编译器没有报错?
    当然,如果A中的i是private的,B中定义的i的也是private,二者肯定没有任何关系。
      

  4.   


    希望能稍微说详细点。你知道,我有很多的猜测……。ab当然归根到底是A的一个实例,但是为什么它的方法偏偏又是B类中重写后的方法?
    谢谢!
      

  5.   

    即使是public的也没有关系,override是对方法而言,当然出去被private,public,protected的方法。field没有覆盖的问题,可能会被隐藏。
    就是说父类中定义了i,子类中也定义了i,这时候访问父类中的i(如果可以的话)就要super.i来指明要访问的是父类的。
    不知道看的是什么书,极度不推荐。
      

  6.   

    这就是多态了,具体要看多态的实际原理了,没有研究过。看一参考一下C++中的virtual table,原理差不多。
    ab指向的是B的实例,ab只是一个类型为A的引用。
      

  7.   


    我常常把引用理解为C++中的指针。但是,我记得,如果在C++中A类的一个指针pa指向B类的对象b时,通过pa调用的方法应该还是原始A类的方法,不会是B改写过的(虚函数除外)。
    可能这就是Java与C++的不同之处吧,是吗?
      

  8.   

    C++需要指定方法为虚的,java不需要指定,除了我说的几种情况都是virtual的。
    引用其实就是C++里的指针(当然去掉了很多特性,但基本可以理解为地址,尤其传参数的时候更是和C++的传地址一样),其实说引用更容易让C++人员迷惑。
      

  9.   

    建议看看Core Java,里面的概念应该说的很清楚了,也和C++进行了很多对比.