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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 执笔梦 金牌黑马   /  2014-4-24 18:51  /  1348 人查看  /  8 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 执笔梦 于 2014-4-25 16:27 编辑

//会报空指针异常。
class Parent{
        String name;
        public Parent(){
                System.out.println(this.getClass())    //为什么在这,this代表Child?
                info();                    //也就是为什么这里会调用子类的info();
               
        }
        public void info(){
                name="CC";
        }
        
}

class Child extends Parent{
        public Child(){
              info();
        }

        public void info(){

         name.length();

        }
}
public class MainClass{
        public static void  main(String[] args){
                Child child = new Child();
        }
}

点评

认真去看视频  发表于 2014-4-24 19:50

8 个回复

正序浏览
class Parent{
         String name;
         public Parent(){
                 System.out.println(this.getClass())    //为什么在这,this代表Child?
                                                 //main方法中new 的是一个子类对象,会进入到Child类的构造方法,通过super进入parent构造方法中
                                             //这里的this代表的是child对象,所以getClass是Child。
                info();                    //也就是为什么这里会调用子类的info();                 
                                    //这里调用info方法,因为在子类中重写了info方法,所以子类对象调用子类方法。
         }
         public void info(){
                 name="CC";
         }         
}
class Child extends Parent{
         public Child(){                     //默认的这里有个super()方法
              //super();
               info();
         }
         public void info(){                           //至于空指针异常,是父类中的name是默认初始化的,值是null,被子类对象调用info方法后,执行子类
                                                                 //info方法。name为空,所以name.length()要报空指针异常
          name.length();
         }
}
public class MainClass{
         public static void  main(String[] args){
                 Child child = new Child();
         }
}

回复 使用道具 举报
这段代码的执行结果就看你new谁的对象了。
当你new Parent()对象时,那个this就指向的是父类,info()方法也会执行父类的,因为你new谁就执行谁的构造方法。执行结果为:class 包.Parent
当你new Child()对象时,那个this就指向的是子类,info()方法会执行子类的,因为它调用的是子类的构造方法,子类构造方法中第一行默认的会有一个super()来执行父类中的构造方法,此时this自然而然指的是子类了,子类info()方法覆盖父类的info()方法,执行的是子类的info()方法,由于父类没给name赋初值,自然会报空指针异常。
回复 使用道具 举报
当你创建子类对象的时候,在子类的构造函数第一行,是隐式的super(),所以执行的是父类的构造函数。就执行了这一句  :  System.out.println(this.getClass())   。但是你要明白的是此this指向的是子类对象,因为你创建的是子类对象,this就指向子类。。
由于函数的覆盖特性,子类的info()函数覆盖了父类的info()函数,所以就调用子类的info()。此时由于你子类的info()是name.length(),但是你的父类在定义name时并没有赋予初值,所以就出现了空指针异常。。。
回复 使用道具 举报 1 0
你这实例很不错,我细细研究了下,的出了一个颇有意思的结论
首先 Child extends Parent 在new Child对象的时候 同时会默认去调用父类的无参构造函数
至于这个在父类的this 指针 为什么在new子类的时候 打印出来的class是属于子类的
其实也很好解释 , 对于JVM来说, 你new 的是子类对象 而this指针式代表对象自己,JVM只知道是子类new了对象
所以在父类构造方法中的this 指向的就是子类对象---注意哦 在父类的构造方法中 此时的this指针都是指向的子类对象
至于 会报空指针异常,原因也很简单
子类覆盖了父类的方法,在父类调用该方法的时候,会优先从子类方法中寻找,如果找到了,就执行子类的方法
如果没找到,才会去执行父类的方法,至于原理,我也想了下,应该和ClassLoader的 委托模型脱不了关系
  1. package test.cn;
  2. class Parent{
  3.         String name= "234";
  4.         public Parent(){
  5.                 System.out.println("Parent  构造方法");
  6.                 System.out.println(this.getClass());
  7.                 info();                    //如果new的是子类对象 会优先使用子类的覆盖方法
  8.                
  9.         }
  10.         public void info(){
  11.                 name="CC";
  12.                 System.out.println("Parent info");
  13.         }
  14.         
  15. }

  16. class Child extends Parent{
  17.         public Child(){
  18.                 System.out.println("Child 构造方法");
  19.                 info();
  20.         }

  21.         public void info(){
  22.          System.out.println("Child -- info");
  23.          name.length();

  24.         }
  25. }
  26. public class MainClass{
  27.         public static void  main(String[] args){
  28.                
  29.                 new Child();
  30.         }
  31. }
复制代码



回复 使用道具 举报
首先String name;这里没有初始化 也就是说 这是个空引用,该引用没有指向任何对象,
而你的父类函数info用于给name赋值,但是子类覆写了该方法。
所以你创建子类对象时,那么它调用构造方法初始化对象时,调用的就是子类的info,
而name.length()自然会空指针异常
如果你给name赋了初值就不会了。比如:
  1. public class Text111 {

  2.         public static void main(String[] args) {

  3.                 Child child = new Child();
  4.                 Parent s = new Parent();
  5.         }

  6. }

  7. //会报空指针异常。
  8. class Parent{
  9.       String name="nnero";
  10.       public Parent(){
  11.               System.out.println(this.getClass());    //为什么在这,this代表Child?
  12.               info();                    //也就是为什么这里会调用子类的info();
  13.               
  14.       }
  15.       public void info(){
  16.               name="CC";
  17.       }
  18.       
  19. }

  20. class Child extends Parent{
  21.       public Child(){
  22.                       super();
  23.            info();
  24.       }

  25.       public void info(){

  26.               name.length();

  27.       }
  28. }
复制代码

这里的代码就是赋了初值 ,就不会空指针异常了。
或者,你把子类的info改个名字也不会空指针了。
另外你这里创建的是Child对象,子类在调用构造函数的时候,会隐式调用super()这个函数,那么相当于:
  1.       public Child(){
  2.               System.out.println(this.getClass());  
  3.                       info();         
  4.            info();
  5.       }
复制代码

自然就是在子类里初始化,自然就是child。
如果你创建父类对象,就是parent。
回复 使用道具 举报
  1. class Parent
  2. {
  3.         String name;
  4.         public Parent()
  5.         {
  6.                 System.out.println(this.getClass());    //为什么在这,this代表Child?
  7.                 //简单说:哪个对象在调用this所在的函数,this就代表哪个对象。
  8.                 //你创建了子类的对象new child(),child在用构造函数进行初始化对象时,会先调用父类的构造函数
  9.                 info();                    //也就是为什么这里会调用子类的info();
  10.                 //因为这里的info()被子类的info()复写了,所以调用的子类的 info()
  11.                
  12.         }
  13.         public void info()
  14.         {
  15.                 name="CC";
  16.         }
  17.         
  18. }
复制代码
回复 使用道具 举报
你都new Child()了,又不是new Parent(),为什么你会觉得该调用父类的方法??
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马