package cn.com.starit.io;
class Base{
public Base(){
test();
}
public void test(){
System.out.println("aaaaa");
}
}class Sub extends Base{
private String name;
public void test(){
System.out.println("aaaaa"+name.length());//这里为什么会出现空指针异常 啊?
}
}public class test1 {
public static void main(String[] args){
Sub s = new Sub();
}
}
class Base{
public Base(){
test();
}
public void test(){
System.out.println("aaaaa");
}
}class Sub extends Base{
private String name;
public void test(){
System.out.println("aaaaa"+name.length());//这里为什么会出现空指针异常 啊?
}
}public class test1 {
public static void main(String[] args){
Sub s = new Sub();
}
}
改成这个就不会为空了
private String name="";
我可没说 改成private String name="";就不会为空了,呵呵其实改成什么,也为NullPointerException的,因为调用子类的test方法时,子类还没有进行初始化,但所有成员变量已经会有一个初始值,这是加载器默认分配的。这里的name就是null
怎么会是父类调用子类呢?应该是“重写”机制,而和访问权限没有关系,希望大家也手动试一下,具体见解在8楼说明了,thx
已经测过了
因为new Sub()的时候调用了父类的构造方法 然后又调用了test方法 在调用test的之前会检查方法有没有重写 然后因为是子类对象所以会调用Sub里的test方法 这个时候Sub.name还没有赋值 所以会有空指针错误
个人见解...
还是这位大哥聪明。
我没看大家的问题前我试了一下。
其实就是这样,LZ
你这个问题和初始化的顺序也有一定的关系:
1、 JVM首先将class的字节码 load进内存,然后初始化 static value ->static block,到父类 的实力变量,到父类的构造方法,到子类的实力变量,到子类的构造方法。
值得注意的是,对象的创建(creation of new class instances)的时候,
所有的成员变量—包括该类,及它的父类中的成员变量--被分配内存空间,并赋予默认值。(Btw,这里是第一次初始化成员变量)
(b)
为所调用的构造函数初始化其参数变量。(如果有参数)
(c) 如果在构造函数中用this
调用了同类中的其他构造函数,则按照步骤(b)~(f)去处理被调用到的构造函数。
(d)
如果在构造函数中用super调用了其父类的构造函数,则按照步骤(b)~(f)去处理被调用到的父类构造函数。
(e) 按照书写顺序,执行instance
initializer 和 instance variable initializer来初始化成员变量。(Btw,这里是第二次初始化成员变量)
(f)
按照书写
所以你这里的 name属性为 null,null调用 任何方法,都是不允许的。
这里和private无关其实,你在Sub类内部自己通过length()方法访问 name属性,完全可以。
而且要定义为Public就行了