黑马程序员技术交流社区
标题:
一个继承难倒我
[打印本页]
作者:
执笔梦
时间:
2014-4-24 18:51
标题:
一个继承难倒我
本帖最后由 执笔梦 于 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:23
你都new Child()了,又不是new Parent(),为什么你会觉得该调用父类的方法??
作者:
2528870651
时间:
2014-4-24 19:34
class Parent
{
String name;
public Parent()
{
System.out.println(this.getClass()); //为什么在这,this代表Child?
//简单说:哪个对象在调用this所在的函数,this就代表哪个对象。
//你创建了子类的对象new child(),child在用构造函数进行初始化对象时,会先调用父类的构造函数
info(); //也就是为什么这里会调用子类的info();
//因为这里的info()被子类的info()复写了,所以调用的子类的 info()
}
public void info()
{
name="CC";
}
}
复制代码
作者:
NNERO
时间:
2014-4-24 19:35
首先String name;这里没有初始化 也就是说 这是个空引用,该引用没有指向任何对象,
而你的父类函数info用于给name赋值,但是子类覆写了该方法。
所以你创建子类对象时,那么它调用构造方法初始化对象时,调用的就是子类的info,
而name.length()自然会空指针异常
如果你给name赋了初值就不会了。比如:
public class Text111 {
public static void main(String[] args) {
Child child = new Child();
Parent s = new Parent();
}
}
//会报空指针异常。
class Parent{
String name="nnero";
public Parent(){
System.out.println(this.getClass()); //为什么在这,this代表Child?
info(); //也就是为什么这里会调用子类的info();
}
public void info(){
name="CC";
}
}
class Child extends Parent{
public Child(){
super();
info();
}
public void info(){
name.length();
}
}
复制代码
这里的代码就是赋了初值 ,就不会空指针异常了。
或者,你把子类的info改个名字也不会空指针了。
另外你这里创建的是Child对象,子类在调用构造函数的时候,会隐式调用super()这个函数,那么相当于:
public Child(){
System.out.println(this.getClass());
info();
info();
}
复制代码
自然就是在子类里初始化,自然就是child。
如果你创建父类对象,就是parent。
作者:
随风而去
时间:
2014-4-24 19:39
你这实例很不错,我细细研究了下,的出了一个颇有意思的结论
首先 Child extends Parent 在new Child对象的时候 同时会默认去调用父类的无参构造函数
至于这个在父类的this 指针 为什么在new子类的时候 打印出来的class是属于子类的
其实也很好解释 , 对于JVM来说, 你new 的是子类对象 而this指针式代表对象自己,JVM只知道是子类new了对象
所以在父类构造方法中的this 指向的就是子类对象---
注意哦 在父类的构造方法中 此时的this指针都是指向的子类对象
至于 会报空指针异常,原因也很简单
子类覆盖了父类的方法,在父类调用该方法的时候,会优先从子类方法中寻找,如果找到了,就执行子类的方法
如果没找到,才会去执行父类的方法,至于原理,我也想了下,应该和ClassLoader的 委托模型脱不了关系
package test.cn;
class Parent{
String name= "234";
public Parent(){
System.out.println("Parent 构造方法");
System.out.println(this.getClass());
info(); //如果new的是子类对象 会优先使用子类的覆盖方法
}
public void info(){
name="CC";
System.out.println("Parent info");
}
}
class Child extends Parent{
public Child(){
System.out.println("Child 构造方法");
info();
}
public void info(){
System.out.println("Child -- info");
name.length();
}
}
public class MainClass{
public static void main(String[] args){
new Child();
}
}
复制代码
作者:
wyqs92
时间:
2014-4-24 22:12
当你创建子类对象的时候,在子类的构造函数第一行,是隐式的super(),所以执行的是父类的构造函数。就执行了这一句 : System.out.println(this.getClass()) 。但是你要明白的是此this指向的是子类对象,因为你创建的是子类对象,this就指向子类。。
由于函数的覆盖特性,子类的info()函数覆盖了父类的info()函数,所以就调用子类的info()。此时由于你子类的info()是name.length(),但是你的父类在定义name时并没有赋予初值,所以就出现了空指针异常。。。
作者:
eternallove
时间:
2014-4-24 23:52
这段代码的执行结果就看你new谁的对象了。
当你new Parent()对象时,那个this就指向的是父类,info()方法也会执行父类的,因为你new谁就执行谁的构造方法。执行结果为:class 包.Parent
当你new Child()对象时,那个this就指向的是子类,info()方法会执行子类的,因为它调用的是子类的构造方法,子类构造方法中第一行默认的会有一个super()来执行父类中的构造方法,此时this自然而然指的是子类了,子类info()方法覆盖父类的info()方法,执行的是子类的info()方法,由于父类没给name赋初值,自然会报空指针异常。
作者:
四川男人
时间:
2014-4-25 00:32
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();
}
}
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2