上学期学了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)方法,代码如下:

CircularLinkedList<Integer>list1 =new CircularLinkedList<Integer>();
	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)。这样一来,问题就逐渐明了了。

Java中的多态

要满足多态的条件,子类要重写父类的方法。多态是父类引用指向子类对象。

值得注意的是,多态中,若子类中没有重写方法,则就算子类中的方法名和父类中的方法名一样(即子类仅仅重载了父类中的方法),那么不能构成多态,而子类中的这个方法就和它自己创建的一个普通方法是一样的,和父类并没有关系。

另外,在使用多态时,调用子类方法的时候会先去看引用类型中是否有同样的方法,即会先去看此方法是否被重写,如果此方法不是被重写的,也就是说,调用的子类中的方法是重载父类中的方法,父类中实际上是没有这个方法的,那么在调用这个方法的时候就会报错。例子如下:

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