上学期学了java,一个暑假没有用,很多java的“精髓”都忘记了。周末在写数据结构的作业的时候,要求写一个循环链表的类,并且继承之前写的一个线性表的类。因为重写的一些重要的东西忘记了,花了大量的时间一直在报空指针异常,终于发现了问题,并请教了前辈才算是解决了这个问题。
首先,我创建了一个MyAbstractList的父类,里面是一些实现线性表的方法。然后创建了一个CircularLinkedList的子类,继承了MyAbstractList类中的方法。其中,父类里面有两个add()方法,如下:
public void add(E e) {
this.add(index,E e);
System.out.println("Add parent o");
}
public void add(int index,E e) {
System.out.println("Add parent t");
}
接着,我在子类,也就是CircularLinkedList类里面重写了这两个方法,如下:
@Override
public void add(E element) {
super.add(E e);
System.out.println("Add child o");
}
@Override
public void add(int index,E element) {
super.add(index,E e);
System.out.println("Add child t");
}
在测试类里面创建了一个子类对象,并且调用了add(E element)方法,代码如下:
CircularLinkedListlist1 =new CircularLinkedList();
list1.add(3);
}
我的脑海里这段程序的输出应该是这样的:(很久以前写的,现在也忘了当时怎么想的,总之不对)
Add child o
Add parent o
Add parent t
然而事实并非如此,真正的输出是这样的:
Add parent t
Add child t
Add parent o
Add child o
这是为什么呢?原来,因为我new的对象是子类,也就是CircularLinkedList类,所以在父类中的 this.add(int index,E e)时,调用的并非是父类中的add(int index,E e),而是子类中的add(int index,E e)。这样一来,问题就逐渐明了了。
要满足多态的条件,子类要重写父类的方法。多态是父类引用指向子类对象。
值得注意的是,多态中,若子类中没有重写方法,则就算子类中的方法名和父类中的方法名一样(即子类仅仅重载了父类中的方法),那么不能构成多态,而子类中的这个方法就和它自己创建的一个普通方法是一样的,和父类并没有关系。
另外,在使用多态时,调用子类方法的时候会先去看引用类型中是否有同样的方法,即会先去看此方法是否被重写,如果此方法不是被重写的,也就是说,调用的子类中的方法是重载父类中的方法,父类中实际上是没有这个方法的,那么在调用这个方法的时候就会报错。例子如下:
package test;
public class TestPolymorphic {
public static void main(String[] args) {
A test=new B();
test.printl();
}
}
class A{
void printl(int x) {
System.out.println("x is "+x);
}
}
class B extends A{
void printl() {
System.out.println("y is null");
}
}
编译器会给出如下错误提示:
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
The method printl(int) in the type A is not applicable for the arguments ()
当代码修改之后,如下:
public static void main(String[] args) {
A test=new B();
test.printl(10);
}
方法会调用A类中的printl()方法,并且输出结果:x is 10
而当子类中重写了父类中的方法之后,即代码如下:
package test;
public class TestPolymorphic {
public static void main(String[] args) {
A test=new B();
test.printl(10);
}
}
class A{
void printl(int x) {
System.out.println("x is "+x);
}
}
class B extends A{
void printl(int y) {
System.out.println("y is null");
}
}
调用的则是子类中的printl()方法,输出结果为:y is null