探讨 java 的三大特性之一:继承
先回顾一下, Java 面向对象的三大特性包括:封装、继承、多态。
PS:还有一些说四大特性,加了一个抽象
封装:将属性私有化,对外提供访问属性的方法,也可以不提供方法,这个特性叫做封装。
继承:
- 子类拥有父类对象所有的属性和方法(包括私有属性和私有方法),但是父类中的私有属性和方法子类是无法访问,只是拥有。
- 子类可以拥有自己属性和方法,即子类可以对父类进行扩展。
- 子类可以用自己的方式实现父类的方法
多态:多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量到底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。 简单得说,就是一个类有多个子类,在创建类得对象时,不同的子类,表现出来方法结果是不一致的,可以有多种形态。
现在主要探讨,子类拥有父类的所有属性和方法,包括私有属性和私有方法。
父类:
package com.entity; /** * @author Robert_mml */ public class BaseUser { public BaseUser(String name) { this.name = name; } public BaseUser(String name, String age) { this.name = name; this.age = age; } public BaseUser() { System.out.println("父类"); } private BaseUser getInstance() { return new BaseUser(); } private String name; private String age; public String like; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAge() { return age; } public void setAge(String age) { this.age = age; } public String getLike() { return like; } public void setLike(String like) { this.like = like; } public String zToString() { return "BaseUser{" + "name='" + name + '\'' + ", age='" + age + '\'' + ", like='" + like + '\'' + '}'; } }
子类:
package com.entity; /** * @author Robert_mml */ public class SysUser extends BaseUser { private String name; private String age; public String like; public SysUser(String name) { super(name); } public SysUser(){ System.out.println("子类"); } // @Override private SysUser getInstance() { return new SysUser(); } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAge() { return age; } public void setAge(String age) { this.age = age; } @Override public String getLike() { return like; } @Override public void setLike(String like) { this.like = like; } public String getSuperLike() { return super.getLike(); } public void setSuperLike(String like) { super.setLike(like); } public String zToString() { return "SysUser{" + "name='" + name + '\'' + ", age='" + age + '\'' + ", like='" + like + '}' + " BaseUser{ " + super.zToString() + '\'' + '}' + " BaseUser{ " + super.toString() + '\'' + '}'; } }
发现子类拥有父类的私有属性时,子类已经可以自己拥有这些私有属性。并不会出现冲突。子类使用 @Override 标识相同的私有方法时,也会报错。
从这些看来,子类似乎不拥有父类的私有属性。
根据相关资料, 子类创建时,是会先创建一个父类对象,父类对象外层是一个子类,子类包含父类,在外层是子类的独有方法。
当子类和父类拥有相同名称的public属性,使用 @Override 标识依然报错,可以猜测,子类和父类,属性是在不同的内存空间。
Main:
package com.entity; public class Main { public static void main(String[] args) { SysUser sysUser = new SysUser(); sysUser.setLike("乒乓球"); sysUser.setSuperLike("羽毛球"); System.out.println(sysUser.toString()); System.out.println(sysUser.zToString()); } }
结果:
父类 子类 com.entity.SysUser@7cd84586 SysUser{name='null', age='null', like='乒乓球} BaseUser{ BaseUser{name='null', age='null', like='羽毛球'}'} BaseUser{ com.entity.SysUser@7cd84586'}
可以看出,父类的内存空间,是在子类上。
说明,父类在初始化时,是在子类的内存空间上进行初始化的,但是并没有创建一个真正的实例,但是子类属性是跟父类分开的。
PS:当把父类的无参构造方法去掉,仅保留有参构造方法时, 子类必须实现一个相同的有参构造方法,不实现会报错。
当父类拥有多个构造方法,子类只需要实现其中一种即可。
Java 继承父类子类内存分配解释:
https://blog.csdn.net/smithdoudou88/article/details/12756187