java继承中的几点注意事项

继承是面向对象语言的一个重要特征,在进行大型项目开发的时候其优点尤其明显,这里对java中应用继承时的几点注意事项(容易出错的地方)进行了总结。笔者本打算将这几种现象从基本原理上解释一下,但是想来想去都感觉无从下手,因为需要读者比较了解java虚拟机的内部机制,很多东西比较抽象,所以看到这篇文章的读者记住下面这几种现象就行了,如果想深入理解其本质原理,建议大家读一下《深入java虚拟机》这本书。

一、最常见的一种,对象的上转型对象:即运行时多态(这种情况相信大家都知道,为了文章的完整性也放到了这里)

示例:

public class TestExtend{ public static void main(String args[]){ Person p=new Person(); p.disp(); Student s=new Student(); p=s; p.disp(); } } class Person{ int a; public Person(){ a=1; } public void disp(){ System.out.println(a); } } class Student extends Person{ int a; public Student(){ a=2; } public void disp(){ System.out.println(a); } }

解析:上面的程序会先输出1,然后输出2。

输出1时,p指向的就是Person的实例,调用Person类的disp()方法,输出Person实例的属性a=1;输出2时,p指向的是Student的实例,调用Student的disp()方法,输出Student实例的属性a=2。

 

二、情况二

示例:

public class TestExtend{ public static void main(String args[]){ Student s=new Student(); s.disp(); } } class Person{ int a; public Person(){ a=1; } public void disp(){ System.out.println(a); } } class Student extends Person{ int a; public Student(){ a=2; } }

解析:运行上面的程序,输出的是1还是2?你会看到输出的是1!

上面的程序中Person和Student类中都有a属性,我们定义了一个Student的对象s,调用s的disp()方法输出的不是Student的a而是Person的a。相信很多人在运行程序前都会觉得应该输出2,但结果告诉我们输出的就是1!子类Student虽然覆盖了父类的属性a,但子类没有重写父类的disp()方法,对象s调用disp()方法时调用的依然是父类的方法,而父类方法访问的依然是父类的a,而不是子类的a。这里或者重写父类的disp()方法,或者将Student中的int a;注释掉才能输出2!

其实上面程序在逻辑上是有问题的,既然继承了父类的属性,就不应该在子类中从新定义一遍,子类中可以增加属性,但是重写属性没有什么意义!这里这样演示,是想说明这样一种情况。

 

三、情况三:类属性没有多态

示例:

public class TestExtend{ public static void main(String args[]){ Person p; Student s=new Student(); p=s; System.out.println(p.a); } } class Person{ int a; public Person(){ a=1; } public void disp(){ System.out.println(a); } } class Student extends Person{ int a; public Student(){ a=2; } public void disp(){ System.out.println(a); } }

解析:上面的程序输出的是1;

即使在Student类中从新定义了一遍a,并且p指向了Student的实例,上面输出的是依然是Person的a而不是Student的a,属性是没有多态现象的。和上面一样,在子类中定义父类中已经定义了的属性,是没有意义的,既然父类已经有了某个属性,子类直接继承就是了,重写一遍从道理上根本说不清。很多初学者,对继承理解不是很透彻,很多论坛上都在问很多关于在子类中复写了父类的属性,访问中遇到的问题,其实这是自找麻烦。

你可能感兴趣的:(java)