A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 张凯 中级黑马   /  2012-7-24 11:00  /  2257 人查看  /  9 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

  1. class Parent2   
  2. {   
  3.     Parent2 ()   
  4.     {   
  5.         vist();   
  6.     }   
  7.       
  8.     void vist()   
  9.     {   
  10.         System.out.println("Parent Vist");   
  11.     }   
  12. }   
  13.   
  14. public class SubConstructor extends Parent2   
  15. {   
  16.   
  17.     SubConstructor()   
  18.     {   
  19.         vist();   
  20.     }   
  21.       
  22.     void vist()   
  23.     {   
  24.         System.out.println("Sub Vist");   
  25.     }   
  26.   
  27.     public static void main(String[] args)   
  28.     {   
  29.   
  30.         Parent2 parent = new Parent2();   
  31.         parent.vist();   
  32.         System.out.println("---------------");   
  33.         SubConstructor sub = new SubConstructor();   
  34.         sub.vist();   
  35.         System.out.println("---------------");   
  36.     }   
  37.   
  38. }  

复制代码
对于在初始化方法调用方法时,在parent运行初行化方法时,调用的vist方法是parent的还是sub的? 此时子类还未初始化吧,怎么还会调用的是子类的vist方法?

评分

参与人数 1技术分 +1 收起 理由
韦念欣 + 1 赞一个!

查看全部评分

9 个回复

正序浏览
本帖最后由 郑正华 于 2012-7-25 01:12 编辑
姬仁贵 发表于 2012-7-24 15:54
为什么对象已建立就会调用他本身的够着函数呢?这是一个什么机制呢?

构造函数的作用就是给对象进行初始化,对象一建立就会调用与之对应的构造函数。你可以试试以下代码:
class Person
{
       Person()
        {
               System.out.println("我被调用了!");
         }
}
class   Demo
{
          public static void main(String[]  args)
         {
                 Person    p =  new   Person();
          }
}
你运行后就会发现,只写Person    p =  new   Person();   Person类就已经被调用了。
回复 使用道具 举报
多态,记住一句话,,,编译时看左边,,,运行时看右边

解释下,编译时,编译器会检查等号两边是否是同一类型,由于子类继承了父类,所以也是父类的类型,而运行时,会运行实际对象的方法。。。。。。。。。。。。。。。
回复 使用道具 举报
郑正华 发表于 2012-7-24 14:13
楼主的代码结果应该是:
Parent Vist
Parent Vist

为什么对象已建立就会调用他本身的够着函数呢?这是一个什么机制呢?
回复 使用道具 举报
本帖最后由 郑正华 于 2012-7-24 14:17 编辑

楼主的代码结果应该是:
Parent Vist
Parent Vist
---------------
Sub Vist
Sub Vist
Sub Vist
---------------
parent 初始化的对象是父类 Parent2的 ,Parent2的对象一建立,就会调用它本身的构造函数,而Parent2的构造函数里有个visit()方法,就会调用Parent2的visit()方法,所以就输出第一行的“Parent Vist”,之后执行 parent.vist();语句,所以输出了第二行 “Parent Vist“。
sub初始化的对象是子类SubConstructor的 。SubConstructor 的对象一建立,就会调用它本身的构造函数,但是因为是继承关系,所以子类的构造函数里的第一行其实都有一个隐式的语句:super();也就是说子类的构造函数其实是这样子的:
SubConstructor()
{
      super();  ←这条语句是隐藏的,
      vist();
}
这个语句会调用父类的构造方法,然后父类的构造方法就调用父类的visit()方法,但因为子类覆盖了父类的 void vist() 方法,所以执行的语句是子类的void vist() 方法,所以输出了第一行的Sub Vist,第二行第三行的”Sub Vist“输出就和上面的两行”Parent Vist“输出是一个道理了。

评分

参与人数 1技术分 +1 收起 理由
韦念欣 + 1 赞一个!

查看全部评分

回复 使用道具 举报
  1. class Parent2   
  2. {   
  3.     Parent2 ()   
  4.     {
  5.         System.out.println(this.getClass().getName());
  6.         vist();   
  7.     }   
  8.     void vist()   
  9.     {   
  10.         System.out.println("Parent Vist");   
  11.     }   
  12. }   
  13.   
  14. public class SubConstructor extends Parent2   
  15. {   
  16.   
  17.     SubConstructor()   
  18.     {
  19.         vist();   
  20.     }   
  21.       
  22.     void vist()   
  23.     {   
  24.         System.out.println("Sub Vist");   
  25.     }   
  26.   
  27.     public static void main(String[] args)   
  28.     {   
  29.   
  30.         Parent2 parent = new Parent2();   
  31.         parent.vist();   
  32.         System.out.println("---------------");   
  33.         SubConstructor sub = new SubConstructor();   
  34.         sub.vist();   
  35.         System.out.println("---------------");   
  36.     }   
  37.   
  38. }  
复制代码
输出结果:
Parent2
Parent Vist
Parent Vist
---------------
SubConstructor
Sub Vist
Sub Vist
Sub Vist
---------------
说明:SubConstructor构造函数调用Parent2的构造函数时,Parent2里的vist方法实际上是SubConstructor的。
因为this.getClass()得到的是SubConstructor。
回复 使用道具 举报
class Parent2 {
        Parent2 ()   

  {   
                 System.out.println("Parent Vist");

   }   
        

   void vist()   

    {   

        System.out.println("Parent Vist");   

    }

}
  class sun extends Parent2{

         sun()   

           {   

                vist();   

          }   
               

           void vist()   

            {   

             System.out.println("Sub Vist");   
            }   
         

           public static void main(String[] args)   

            {   

         
                Parent2 parent = new Parent2();   

                 parent.vist();  // 编译看左边,运行看右边    这里肯定调用的是父类的啦

                System.out.println("---------------");   
                 sun sub = new sun();   //这里调用的是子类的虽然子类的里边有一个隐是的super但是因为
                                                      //sun继承了Person2那么就复写了vist()方法
                sub.vist();   

               System.out.println("---------------");   

            }  
}
回复 使用道具 举报
class Parent2   

{   

    Parent2 ()   

    {   

        vist();   

    }   

      

    void vist()   

    {   

        System.out.println("Parent Vist");   

    }   

}   

  

public class SubConstructor extends Parent2   

{   

  

    SubConstructor()   

    {   

        vist();   

    }   

      

    void vist()   

    {   

        System.out.println("Sub Vist");   

    }   

  

    public static void main(String[] args)   

    {   

  

        Parent2 parent = new Parent2();   

        parent.vist();//父类的实例化对象调用父类里面的方法。   

        System.out.println("---------------");   

        SubConstructor sub = new SubConstructor();   

        sub.vist();  //子类无参构造函数首先会调用父类的无参构造函数,而父类的无参构造函数里面的vist()方法已经被子类复写,所以在执行过程中没有调用父类的vist(),而是调用了子类的vist()方法。

        System.out.println("---------------");   

    }   
}  
输出结果:
Parent Vist
Parent Vist
---------------
Sub Vist
Sub Vist
Sub Vist
---------------


回复 使用道具 举报
public static void main(String[] args)   

28.    {   

29.  

30.        Parent2 parent = new Parent2();   

31.        parent.vist();   

32.        System.out.println("---------------");   

33.        SubConstructor sub = new SubConstructor();   子类对象实例化先调用父类默认构造函数,可能父类没有找到vist()方法,所以调用了子类的vist()方法
                                                                再调用子类自己的构造方法


34.        sub.vist();   

35.        System.out.println("---------------");   

36.    }
所以结果为:Sub Vist,Sub Vist,Sub Vist
回复 使用道具 举报
本帖最后由 李东升 于 2012-7-24 11:23 编辑
  1. public class Parent2 {
  2.         Parent2 ()   
  3.     {   
  4.                 System.out.println("Parent Vist");
  5.     }   
  6.       
  7.     void vist()   
  8.     {   
  9.         System.out.println("Parent Vist");   
  10.     }
  11. }
  12. public class SubConstructor extends Parent2{
  13.          SubConstructor()   
  14.             {   
  15.                 vist();   
  16.             }   
  17.                
  18.             void vist()   
  19.             {   
  20.                 System.out.println("Sub Vist");   
  21.             }   
  22.          
  23.             public static void main(String[] args)   
  24.             {   
  25.          
  26.                 Parent2 parent = new Parent2();   
  27.                 parent.vist();   
  28.                 System.out.println("---------------");   
  29.                 SubConstructor sub = new SubConstructor();   
  30.                 sub.vist();   
  31.                 System.out.println("---------------");   
  32.             }  
  33. }
复制代码
我把代码改成这样了,输出正常了。
我这么理解了,当子类实例化的时候,也就是SubConstructor实例化得时候,只调用了父类Parpent2的构造函数,后面的vist()方法还没来得及加载,构造函数调用这个方法就失败了,转而调用自己的vist()方法。自己的vist()方法在new SubConstructor()的时候,已经加载上了。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马