0 0

求!哪位大大帮忙看看为什么是空指针异常?5

两个接口InterfaceA, InterfaceB:

public interface InterfaceA {
      
void methodA();
}




public interface InterfaceB {
     
void methodB();
}

两个类A,B分别实现此两个接口:

public class A implements InterfaceA {
     
public void methodA() {
System.out.println("A implements InterfaceA");}
}



public class B implements InterfaceB {
     
public void methodB() {System.out.println("B implements InterfaceB");}
}

父类Super中,两个接口作为实例变量

public class Super {

public InterfaceA a;
public InterfaceB b;

public void useMethodA()  {

try{
a.methodA();
} catch (Exception ex){
System.out.println(ex.getMessage());
}

}

public void useMethodB(){
try{
b.methodB();
} catch (Exception ex){
System.out.println(ex.getMessage());
}
}
}



子类Son继承父类,(问题来乐!这时候public InterfaceA a = new A();可以成立的?new一个A的对象 然后直接可以赋给类型为InterfaceA的对象?)

public class Son extends Super {
      public InterfaceA a = new A();
      public InterfaceB b = new B();
}

写一个TestDrive, 编译成功,并正常调用了实现了接口的方法!

public class TestDrive {

/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
       Son s = new Son();
       s.useMethodA();
       s.useMethodB();
}

}

控制台输出:

null
null


问题补充:
meng22623 写道
public class Son extends Super {
      public InterfaceA a = new A();
      public InterfaceB b = new B();
}
这里你声明的a和b与父类的a和b根本没有关系。子类的a和b是自己特有的,你根本没有引父类的a和b。
就像feige1008这位兄台说的,
public class Son extends Super {
      a = new A();
      b = new B();
}
改成这样就可以了。


明白了!这里重新声明了一次~ 这样子类的useMethod方法就无法找到相关的实例变量,而成为空指针。

问题补充:
AngelAndAngel 写道
呵呵,我明白lz的意思了,我copy了一下你的代码,看了一下,我一开始也迷惑了。因为我开始觉得不应该是null,而是打印出那几个语句。我最初是这么想的:
Son既然是继承Super,并且也有两个
      InterfaceA a
     InterfaceB b
那么应该来说是继承并重写了父类的属性,也就是说a,b都应该是初始化了的,所以在调用的时候应该不会为null。

其实不是这样的,Son继承了Super,所以继承了Super的属性和方法,而这个时候呢,方法并没有重写,还是沿用了父类Super的,那么父类方法里面所有的元素都保持父类自己的特色,根本不会下放到子类,而父类的a,b都没有实例化,所以出现了null。


原因找到了,子类我重新声明了一次变量,因此方法useMethodA和useMethodB用到的a和b并没有初始化,因此用useMethod的时候,无法读取a和b的变量。

如果我不声明a,b 
直接用 a = new A(); b = new B();

就可以了,而不用重写那两个方法,因为方法已经从父类继承下来了,只要有相关的变量就可以了。

问题补充:
AngelAndAngel 写道
lz,其实你明白的 只是一个浅显的表象。按道理说,子类的属性跟父类的肯定有关系的(怎么会没关系呢),只是说在这里你子类方法没有重写,所以看不出有关系,而这个误区才刚刚解释了你的现象而已。
你仔细看一下我的回答。


我明白你的意思,但我的目的是想方法在父类就已经写好了,子类不用再重写。

因此我是希望将父类声明的a,b在子类实例化,然后在父类进行运算。但问题就出在,我子类的两个实例变量重新声明了,因此useMethod里用到的变量a,b并没有进行初始化。^^
OO 
2011年8月30日 01:34

6个答案 按时间排序 按投票排序

0 0

采纳的答案

public class Son extends Super {
      public InterfaceA a = new A();
      public InterfaceB b = new B();
}
这里你声明的a和b与父类的a和b根本没有关系。子类的a和b是自己特有的,你根本没有引父类的a和b。
就像feige1008这位兄台说的,
public class Son extends Super {
      a = new A();
      b = new B();
}
改成这样就可以了。

2011年8月30日 10:25
0 0

lz,其实你明白的 只是一个浅显的表象。按道理说,子类的属性跟父类的肯定有关系的(怎么会没关系呢),只是说在这里你子类方法没有重写,所以看不出有关系,而这个误区才刚刚解释了你的现象而已。
你仔细看一下我的回答。

2011年8月30日 12:50
0 0

public class Son extends Super {
      public InterfaceA a = new A();
      public InterfaceB b = new B();
}

此类变成
public class Son extends Super {
      a = new A();
      b = new B();
}
就好了。

2011年8月30日 09:34
0 0

呵呵,我明白lz的意思了,我copy了一下你的代码,看了一下,我一开始也迷惑了。因为我开始觉得不应该是null,而是打印出那几个语句。我最初是这么想的:
Son既然是继承Super,并且也有两个
      InterfaceA a
     InterfaceB b
那么应该来说是继承并重写了父类的属性,也就是说a,b都应该是初始化了的,所以在调用的时候应该不会为null。

其实不是这样的,Son继承了Super,所以继承了Super的属性和方法,而这个时候呢,方法并没有重写,还是沿用了父类Super的,那么父类方法里面所有的元素都保持父类自己的特色,根本不会下放到子类,而父类的a,b都没有实例化,所以出现了null。

2011年8月30日 09:20
0 0

InterfaceA a   InterfaceB b 你申明了两次,初始化了子类的,父类中的却是没有初始化的。

2011年8月30日 09:19
0 0

引用
问题来乐!这时候public InterfaceA a = new A();可以成立的?new一个A的对象 然后直接可以赋给类型为InterfaceA的对象?


只要A实现了实现了InterfaceA 接口就可以这么赋值,自动上转型,就好比
Object str = new String();或List list = new ArrayList()一个样

引用
控制台输出:

null
null


不会输出null的吧

public class Son extends Super {
      public InterfaceA a = new A();
      public InterfaceB b = new B();
}

Super类声明了两个字段a和b,并初始化为默认值null,子类Son又声明了两个字段a和b
Super类中useMethodA和useMethodB使用的还是Super类声明的a和b,因为没有初始化,会NullPointerException

如果要在子类初始化父类声明的对象,这样就可以了:
public class Son extends Super {
      a = new A();
      b = new B();
}

2011年8月30日 07:44

相关推荐

Global site tag (gtag.js) - Google Analytics