关于继承与多态
2019-12-19 16:04:54来源:博客园 阅读 ()
关于继承与多态
关于继承与多态的几点总结
1、父类的所有方法都能被继承吗?能被重写吗?能表现出多态性吗?
1.1 非静态方法
1.1.1 被public、default、protected修饰的非静态方法
能被子类继承,如果没有被final修饰,则能被重写,当父类引用指向子类对象时,表现出多态性。
1.1.2 被private修饰的非静态方法
不能被子类继承,更不能被重写,没有多态性(有的人理解为父类的所有包括私有的成员都能被继承,只是在子类中不可见,我更倾向于前者)。当子类中出现与父类私有方法名和参数相同的时候会发生什么呢?
class Parent{ private void f() { System.out.println("parent"); } public static void main(String[] args) { Parent p = new Child(); p.f(); } } class Child extends Parent{ public void f() { //父类的私有方法在子类中不可见,子类的f()方法是一个全新的方法,编译器认为f()方法没有被重写
System.out.println("child");
}
}
打印结果:
parent
1.2 静态方法
静态方法可以被继承,不能被重写,也就不能表现出多态性
class Parent{
public static void f() {
System.out.println("parent");
}
}
class Child extends Parent{
public static void f() {
System.out.println("child");
}
public static void main(String[] args) {
Parent p = new Child(); //静态方法能被继承,但不能被重写
p.f();
Child c = new Child();
c.f();
}
}
打印结果:
parent
child
1.3 构造方法
构造方法不能被继承,不能被重写,没有多态性。
构造方法既不是静态方法也不是非静态方法,构造方法中会有一个this对象作为参数传进去,所以我们可以在构造方法内部对对象属性进行初始化,也可以在构造方法内调用非静态方法。
如果该非静态方法被重写过,那么构造器内部会不会存在多态行为呢?参考Java编程思想中的一个例子:
class Glyph {
void draw() {
System.out.println("Glyph.draw()");
}
Glyph() {
System.out.println("Glyph() before draw()");
draw();
System.out.println("Glyph() after draw()");
}
}
class RoundGlyph extends Glyph {
private int radius = 1;
RoundGlyph(int r) {
radius = r;
System.out.println("RoundGlyph.RoundGLyph(), radius = " + radius);
}
void draw() {
System.out.println("RoundGlyph.draw(), radius = " + radius);
}
}
class RolyConstructors {
public static void main(String[] args) {
new RoundGlyph(5);
}
}
在父类构造器中调用被子类重写的非静态方法,会发生多态行为,但这并不是我们想要的结果,原因如下:
- 在其他任何事物发生之前,将分配给对象的存储空间初始化为二进制的零;
- 如前所述那样调用基类构造器。此时,调用被覆盖后的draw()方法(要在调用RoundGlyph构造器之前调用),由于步骤1的缘故,我们此时会发现radius的值为0;
- 按照声明的顺序调用成员的初始化方法;
- 调用导出类的构造器主体。
因此,在编写构造器中有一条有效的准则:“用尽可能简单的方法使对象进入正常状态;如果可以的话,避免调用其他方法”。在构造器中,唯一能够安全调用的是基类中的final方法(包括private方法),因为这些方法不能被子类覆盖,也就不会出现上述的问题。
2、父类的所有属性都能被继承吗?能被重写吗?能表现出多态性吗?
2.1 被public,default,protected修饰的属性
都能被继承(与是否是静态的无关),不能被重写,没有多态性。当子类中定义了与父类相同的属性时,子类会在不同的存储空间同时保留自己的和父类的属性
class Child extends Parent {
public static int a = 2;
public void getA() {
System.out.println("a = "+a);
}
public void ParentA() {
System.out.println("super.a = " + super.a);
}
public static void main(String[] args) {
Parent p = new Child();
System.out.println(p.a); //任何域访问操作都由编译器解析
Child c = new Child();
c.getA(); //直接访问field默认会获取自己的域
c.ParentA(); //通过super.field能获取父类的域
}
}
2.1 被private修饰的属性
个人理解为可以被继承,但是不能直接访问,能通过父类public、default、或protected方法间接访问(也有人理解为不能为继承)
class Parent {
private int a;
public Parent(int a) {
this.a = a;
}
public int getA() {
return a;
}
}
class Child extends Parent {
public Child(int a) {
super(a);
}
public static void main(String[] args) {
Child c = new Child(1);
System.out.println(c.getA()); //结果为1
}
}
当父类和子类存在相同私有属性时:
class Parent {
private int a;
public Parent(int a) {
this.a = a;
}
public int getA() {
return a;
}
}
class Child extends Parent {
private int a = 2;
public Child(int a) {
super(a);
}
public static void main(String[] args) {
Child c = new Child(1);
System.out.println(c.getA()); //1
System.out.println(c.a); //2
}
}
关于继承与多态以及对象初始化过程还有很多不是很理解的地方,先记录下来,等日后有时间研究一下java虚拟机的原理再来完善!
原文链接:https://www.cnblogs.com/xiaohang123/p/12070385.html
如有疑问请与原作者联系
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- 类的继承,方法重新中修饰符如何定义 2020-06-10
- Java--Java的继承性 2020-05-26
- 怎么自学JAVA开发? 2020-05-22
- 关于序列化的 10 几个问题,你顶得住不?.md 2020-05-19
- java“单根继承结构” 2020-05-17
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash