在构造方法中调用被子类重写的方法抛出异常

young_smile 2009-11-19 12:47:22
代码抛出的异常,是因为父类构造方法调用了被子类重写的方法test(),
这里不在执行父类的test()方法,而是子类的test()方法。

我想这应该与对象在内存中的结构有关,所以问题如下:
1,Sub s = new Sub();时内存的结构是怎么样的?
2,书上例子前有句话,“不用在父类中调用被子类重写的方法”,这句话是否可以改为“不能。。。”?

class Base
{
public Base()
{
test();
}
public void test()
{
System.out.println("将被子类重写的方法");
}
}
class Sub extends Base
{
private String name;
public void test()
{
System.out.println("子类重写父类的方法,其name字符串长度" + name.length());
}
public static void main(String[] args)
{
//下面代码会引发空指针异常
Sub s = new Sub();
}
}
...全文
289 10 打赏 收藏 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
young_smile 2009-11-20
  • 打赏
  • 举报
回复
问题解决了。

class Base
{
public Base()
{
test();
}
public void test()
{
System.out.println("将被子类重写的方法");
}
}
class Sub extends Base
{
private String name;
public Sub()
{
super();
}
public void test()
{
System.out.println("子类重写父类的方法,其name字符串长度" + name.length());
}
public static void main(String[] args)
{
//下面代码会引发空指针异常
Sub s = new Sub();
}
}
------------------------------------------------------------------------------

Sub s = new Sub();
上述代码在运行错误,在于在父类构造方法中调用了被子类重写的方法。

中间有两个问题值得思考:

(1),父类构造方法调用test()为什么去执行子类中的test()?
因为s在编译时类型和执行时类型都是Sub,所以调用了子类Sub的test()方法,也是说s的实际类型是Sub。

(2),为什么抛出NullPointerException异常?

实例变量的初始化按照如下步骤递归进行:

1. 绑定构造器参数,分配内存和隐式初始化实例变量。

2. 如果显式使用 this(),递归调用(跳至1开始),然
后跳至第5步。

3. 如果隐式或显式的 super 调用,递归调用(跳至1
开始) , 然后跳至第5步 , Object 除外。

4. 执行显式的实例变量初始化。

5. 执行当前构造器的构造体。

也就是说,实例化对象的时候先执行构造方法,再显式初始化实例变量。
上述代码执行子类构造方法是去掉用了父类构造方法,父类构造调用了子类实例方法,
子类实例方法引用了子类实例变量name,此时子类的实例变量name并没有显示初始化,
只进行了隐式初始化(隐式初始化是将变量赋默认值),name=null,所以抛出了NullPointerException。

machiatto19881031 2009-11-19
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 feng_jyie 的回复:]
引用 2 楼 justinavril 的回复:
你的空指针异常是因为你的name字符串没有初始化导致的,与其他的无关!把你的子类的test方法替换成下面的,你看还有错误嘛?
Java codeSystem.out.println("子类重写父类的方法,其name字符串长度"+"a".length());

应该是这个道理,父类调用子类方法,子类name属性在初始化之前就被调用了,所以会空指针异常。建议不要在构造方法中调用子类方法。
[/Quote]

支持~
whut0802 2009-11-19
  • 打赏
  • 举报
回复
调用Test方法的时候name还没有赋值,即使你在private String name这句给它赋值了,也会抛异常,自己可以debug一下。
chenzhp 2009-11-19
  • 打赏
  • 举报
回复
test还没有产生啊。
zuomingyu2 2009-11-19
  • 打赏
  • 举报
回复
name 没赋值
justinavril 2009-11-19
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 gao11811 的回复:]
原来如此,在初始化s的时候,首先执行父类的构造器,直接调用子类的test,所以name还没有
[/Quote]
恩 没错
gao11811 2009-11-19
  • 打赏
  • 举报
回复
原来如此,在初始化s的时候,首先执行父类的构造器,直接调用子类的test,所以name还没有
feng_jyie 2009-11-19
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 justinavril 的回复:]
你的空指针异常是因为你的name字符串没有初始化导致的,与其他的无关!把你的子类的test方法替换成下面的,你看还有错误嘛?
Java codeSystem.out.println("子类重写父类的方法,其name字符串长度"+"a".length());
[/Quote]
应该是这个道理,父类调用子类方法,子类name属性在初始化之前就被调用了,所以会空指针异常。建议不要在构造方法中调用子类方法。
justinavril 2009-11-19
  • 打赏
  • 举报
回复
你的空指针异常是因为你的name字符串没有初始化导致的,与其他的无关!把你的子类的test方法替换成下面的,你看还有错误嘛?
System.out.println("子类重写父类的方法,其name字符串长度" + "a".length());
gao11811 2009-11-19
  • 打赏
  • 举报
回复
我也想知道,也许的确不能
但是为什么呢。。

62,620

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧