黑马程序员技术交流社区

标题: 很有意义的一道多态题,希望会的朋友能给与清晰的解释 [打印本页]

作者: zhuiyi0819    时间: 2013-4-13 23:22
标题: 很有意义的一道多态题,希望会的朋友能给与清晰的解释
本帖最后由 zhuiyi0819 于 2013-4-14 00:29 编辑

class A {
        private int i = 2;
        public A() {
                fun();
        }
        
        public void fun() {
                System.out.println(i);
        }
}

class B extends A {
        private int i = 22;
        
        public B() {
                i = 222;
        }
        
        public void fun() {
                System.out.println(i);
        }
}

public class Test {
        public static void main(String[] args) {
                B b = new B();
        }
}
作者: 李易烜    时间: 2013-4-13 23:41
class B继承 class A,并且 class B 覆写了 class A的  public void fun() {}
作者: 张先龙    时间: 2013-4-13 23:47
我试了一下  结果为0  想了一下  我觉得应该是这样 不知道对不对 子类会隐式调用父类的无参构造方法,在这个例子里面,父类虽然有private int i=1这个看似是初始化的语句;但是父类的无参构造方法调用的fun()函数打印的i并不是对象传进来的i,即 i的1 并没有赋值给这个对象,所以打印的i的值是系统默认的初值,即0。
作者: mvplee    时间: 2013-4-13 23:48
永远不要去继承一个普通类。
作者: 通行天下    时间: 2013-4-13 23:54
本帖最后由 通行天下 于 2013-4-13 23:55 编辑
  1. class A {
  2.          private int i = 2;
  3.          public A() {
  4.                  fun();
  5.          }
  6.          
  7.         public void fun() {
  8.                  System.out.println("A:"+i);
  9.          }
  10. }

  11. class B extends A {
  12.          private int i = 22;
  13.          
  14.         public B() {
  15.                  super();//这一句是程序默认有的,所以这句会先去调用父类(A)的构造方法A()。
  16.                  i = 222;
  17.          }
  18.          
  19.         public void fun() {
  20.                  System.out.println("B:"+i);
  21.          }
  22. }

  23. public class Test {
  24.          public static void main(String[] args) {
  25.                  B b = new B();
  26.          }
  27. }
  28. /*
  29. 以上程序的执行过程是:B b = new B()---->public B()----->super()----->public A()----->fun()(这里由于多态的存在调用的是子类的方法fun())
  30. 又由于在整个过程中变量i根本就来不及初始化赋值,所以i只能是系统的默认值0;故打印结果为:B:0.
  31. */
复制代码

作者: 林声荣    时间: 2013-4-14 00:04
你上面的代码似乎没用用到多态吧?只是类B继承了类A,然后子类B覆写了类A中的方法等一些常规操作;
如果是多态,测试类的代码就应该一下变动吧?
public class Test {
         public static void main(String[] args) {
                 A b = new B();
         }
}
下面是我在学多态做的笔记希望对你有用吧、、、
多态:
  多态的体现
  父类的引用指向自己的子类对象;
  父类的引用也可以接收自己的子类对象;
  多态的前提
  必须是类与类之间有关系,要么继承,要么实现;
  通常有个前提:存在覆盖;
  多态的好处
  多态的出现提高了程序的扩展性;
  多态的弊端
  提高了扩展性,但是只能使用父类的引用访问父类中的成员;
  小知识点:判断一个类型的引用是指向的对象是否符合该类型用关键字instanceof
  如:if(a instanceof b) a为一个引用对象,b为类名;
  转型:强制将父类的引用转成子类的对象
  父类 f = new 子类();
  1、在多态中非静态成员函数的特点:(简单总结:编译看左边,运行看右边)
  在编译时期:参阅的引用型变量所属类中是否有调用方法,如果有编译通过,如果没有,编译        失败; 如:父类 父类引用f  = new 子类()
  f . method1();                //method1()为方法;
  如果父类中含有method1()方法,则编译成功;否则失败;
  在运行时期:参阅对象所属类中是否有调用方法;
  运行时:调用的方法为 子类中的method1()方法;
  2、在多态静态成员函数的特点:无论编译和运行,都参考左边;
  3、在多态中成员变量的特点:无论在编译和运行都参考左边(引用变量所属的类);
作者: hacket    时间: 2013-4-14 00:12
  1. class A {
  2.         private static int i = 2;
  3.         public A() {

  4.                         System.out.println("1.A()...");               
  5.             fun();
  6.                
  7.         }
  8.         
  9.         public void fun() {
  10.                                 System.out.println("A fun()...");
  11.                 System.out.println(i);
  12.         }
  13. }

  14. class B extends A {
  15.         private static  int i = 22;// static,若这里加上static,则i打印出来为22,因为i为静态的,比构造方法先加载
  16.         
  17.         public B() {
  18.                         i = 222;
  19.                         System.out.println("3.B()...");
  20.         }
  21.      
  22.         public void fun() {
  23.                                 System.out.println("2. B fun()...");
  24.                 System.out.println(i);
  25.         }
  26. }
  27. public class Test {
  28.         public static void main(String[] args) {
  29.                 B b = new B();
  30.         }
  31. }

  32. /*
  33.          B b = new B();
  34.          此时走B的构造函数,但由于其继承自A类,故又走A的构造方法public A(),
  35.          调用fun(),注意这里是new B(),也就是B的对象,根据多态原则,子类覆盖了
  36.          父类的方法,走子类方法,故调用了子类的B fun()方法,然后打印i,由于i还没有
  37.          显示初始化,故默认初始化为0,若在B中i加上static,则为22,因为static变量优先于构造方法。
  38.          ,所以就出现了,奇妙的情景。

  39. */
复制代码
对象的初始化顺序:


  1.首先执行父类静态的内容,父类静态的内容执行完毕后;
  2.接着去执行子类的静态的内容,当子类的静态内容执行完毕之后;
  3.再去看父类有没有非静态代码块,如果有就执行父类的非静态代码块,父类的非静态代码块执行完毕;
  4.接着执行父类的构造方法,父类的构造方法执行完毕之后;
  5.它接着去看子类有没有非静态代码块,如果有就执行子类的非静态代码块,子类的非静态代码块执行完毕;
  6.去执行子类的构造方法。

  总之一句话,静态代码块内容先执行,接着执行父类非静态代码块和构造方法,
  然后执行子类非静态代码块和构造方法。

注意:子类的构造方法,不管这个构造方法带不带参数,默认的它都会先去寻找父类的不带参数的构造方法。
如果父类没有不带参数的构造方法,那么子类必须用supper关键子来调用父类带参数的构造方法,否则编译不能通过。



作者: 16463535    时间: 2013-4-14 00:32
我大胆的猜测一下。说的不对,不要见笑。
当程序执行 B b = new B();时,
public B()
{
        //super();    因为这里有一个隐式的 super语句
            i = 222;
    }
    因为上面的super语句,程序走了A类的空参数构造方法。
A类空参数构造方法中 调用了fun()方法。
B类中已经重写了fun()方法,那么A类调用的fun()方法,其实执行的是B类的fun()方法。此时打印的 i  是B类定义的 i 。可B类中的 i  确实有初始化的值,可结果是0.我猜想,B类的fun()方法打印 i 的时候,B类的对象并没有完全建立,即便B类中有这个 变量 i ,那么 i 的值,也是初始化 值 0.






欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2