Java 继承后访问成员的特点
继承后的特点 -- 成员变量
对象访问成员变量时, 会先在子类中查找有没有定义对应的变量, 若子类中存在就会就近使用子类中的变量, 若子类中没有定义就会沿着继承关系往上找有没有定义相应的变量, 若父类中也没有则编译不通过. 代码示例:classFu{
// Fu 类中的成员变量.
intnum=5;
intnum2=7;
}
classZiextendsFu{
// Zi 类中的成员变量
intnum=6;
publicvoidshow(){
// 访问父类中的 num2
System.out.println("num2="+num2);
// 访问子类中的 num
System.out.println("num="+num);
}
}
publicclassExtendsDemo0{
publicstaticvoidmain(String[]args){
// 创建子类对象
Ziz=newZi();
// 调用子类中的 show 方法
z.show();
}
}
演示结果:
num2=7
num=6
子父类中出现了同名的成员变量时, 在子类中访问父类中非私有成员变量, 需要使用 super 关键字, 用法类似于 this .
使用格式:
super. 父类成员变量名
代码如下:classZiextendsFu{
// Zi 类中的成员变量
intnum=6;
publicvoidshow(){
// 访问父类中的 num
System.out.println("Fu num2="+num2);
// 访问父类中的 num
System.out.println("Fu num="+super.num);
}
}
演示结果:Funum=7
Zinum=5
Fu 类中的私有成员变量, 子类是不能直接访问的. 编码时, 遵循封装的原则, 使用 private 修饰成员变量, 可以在父类中提供公共的 getXxx 方法和 setXxx 方法来访问.
super 和 this
父类空间优先于子类对象产生
在每次创建子类对象时, 先初始化父类空间, 再创建其子类对象本身. 目的在于子类对象中包含了其对应的父类空间, 便可以包含其父类的成员. 代码体现在子类的构造方法调用时, 一定先调用父类的构造方法. 理解图解如下:
super 和 this 的含义
super : 代表父类的存储空间标识 (可以理解为父类的引用).
this : 代表当前对象的引用 (谁调用就代表谁).
super 和 this 的用法
this. 成员变量 -- 本类的
super. 成员变量 -- 父类的
this. 成员方法名 () -- 本类的
super. 成员方法名 () -- 父类的
代码示例:classAnimal{
publicvoideat(){
System.out.println("animal : eat");
}
}
classCatextendsAnimal{
publicvoideat(){
System.out.println("cat : eat");
}
publicvoideatTest(){
this.eat();// this 调用本类的方法
super.eat();// super 调用父类的方法
}
}
publicclassExtendsDemo08{
publicstaticvoidmain(String[]args){
Animala=newAnimal();
a.eat();
Catc=newCat();
c.eatTest();
}
}
输出结果为:animal:eat
cat:eat
animal:eat
注意:
通过 super 引用属性, 方法, 构造器时, 都要求该成员是可见的, 即该成员的修饰符不能是 private 的, 跨包的话还不能是缺省的.
super 的追溯不仅限于直接父类
如果某个属性或方法前面使用 "this.", 那么先从本类中查找, 如果未找到, 会沿着继承关系往上找
如果某个属性或方法前面使用 "super.", 那么先从直接父类中查找, 如果未找到, 会沿着继承关系往上找
如果某个属性或方法前面既没有 "this.", 也没有 "super.", 遵循就近原则, 先从本类中查找, 如果未找到, 会沿着继承关系往上找
继承后的特点 -- 成员方法
成员方法不重名时
如果子, 父类中的方法不重名, 这时的调用是没有影响的. 对象调用方法时, 会先在子类中查找有没有定义对应的方法, 若子类中存在就执行子类中定义的方法, 若子类中没有定义就会沿着继承关系往上找有没有定义相应的方法, 若父类中也没有则编译不通过. 代码示例:classFu{
publicvoidshow(){
System.out.println("Fu 类中的 show 方法执行");
}
}
classZiextendsFu{
publicvoidshow2(){
System.out.println("Zi 类中的 show2 方法执行");
}
}
publicclassExtendsDemo04{
publicstaticvoidmain(String[]args){
Ziz=newZi();
// 子类中没有定义 show 方法, 但是可以找从父类继承的 show 方法去执行
z.show();
z.show2();
}
}
成员方法重名 -- 重写 (Override)
如果子, 父类中出现重名的成员方法, 这时的访问是一种特殊情况, 叫做方法重写 (Override).
方法重写 : 子类继承了父类, 可以获得父类的成员变量和成员方法; 可是当父类的某个方法不适合于子类本身的特征时, 在子类中可以根据需要对从父类中继承来的方法进行改造, 也称为方法的重写, 覆写. 在程序执行时, 子类的方法将覆盖父类的方法.
代码如下:classFu{
publicvoidshow(){
System.out.println("Fu show");
}
}
classZiextendsFu{
// 子类重写了父类的 show 方法
publicvoidshow(){
System.out.println("Zi show");
}
}
publicclassExtendsDemo05{
publicstaticvoidmain(String[]args){
Ziz=newZi();
// 子类中有 show 方法, 只执行重写后的 show 方法
z.show();// Zi show
}
}
重写的应用
子类可以根据需要, 定义特定于自己的行为. 既沿袭了父类的功能名称, 又根据子类的需要重新实现父类方法, 从而进行扩展增强. 比如新的手机增加来电显示头像的功能, 代码如下:classPhone{
publicvoidsendMessage(){
System.out.println("发短信");
}
publicvoidcall(){
System.out.println("打电话");
}
publicvoidshowNum(){
System.out.println("来电显示号码");
}
}
// 智能手机类
classNewPhoneextendsPhone{
// 重写父类的来电显示号码功能, 并增加自己的显示姓名和图片功能
publicvoidshowNum(){
// 调用父类已经存在的功能使用 super
super.showNum();
// 增加自己特有显示姓名和图片功能
System.out.println("显示来电姓名");
System.out.println("显示头像");
}
}
publicclassExtendsDemo06{
publicstaticvoidmain(String[]args){
// 创建子类对象
NewPhonenp=newNewPhone();
// 调用父类继承而来的方法
np.call();
// 调用子类重写的方法
np.showNum();
}
}
重写时, 用到 super. 父类成员方法, 表示调用父类的成员方法.
方法重写注意事项
方法名: 必须完全一致
形参列表: 必须完全一致
返回值类型:
如果是基本数据类型和 void, 必须一致
如果是引用数据类型, 重写的方法的返回值类型 <= 被重写方法的返回值类型, Student
修饰符: 重写的方法的修饰符范围 >= 被重写方法的修饰符范围 (public> protected> 缺省 > private)
被重写方法不能被 private,static,final 修饰, 如果跨包的话, 修饰符缺省的也不能被重写, 因为缺省的跨包不可见
继承后的特点 -- 构造方法
首先我们要回忆两个事情, 构造方法的定义格式和作用:
构造方法的名字是与类名一致的. 所以子类是无法继承父类构造方法的.
构造方法的作用是初始化成员变量的. 所以子类的初始化过程中, 必须先执行父类的初始化动作.
子类不会继承父类的构造器, 但是一定会调用父类的构造器
默认情况下, 调用的是父类的无参构造, super() 写或不写都会调用父类的无参构造, 如果要写, 必须在子类构造器首行
如果父类没有无参构造, 必须在子类的构造器首行使用 super(实参列表) 显式调用父类的有参构造, 否则编译报错
super([形参列表]) 和 this([形参列表]) 都必须是在构造方法的第一行, 所以不能同时出现.
代码示例:classFather{
publicFather(){
System.out.println("父类的无参构造");
}
}
classSonextendsFather{
privateStringstr;
privateintnum;
publicSon(){
// 隐含调用了 super(); 子类的构造器中一定会调用父类的构造器, 默认调用父类的无参构造
System.out.println("子类的无参构造");
}
publicSon(Stringstr){
// 隐含调用了 super()
this.str=str;
System.out.println("子类的有参构造 1");
}
publicSon(Stringstr,intnum){
// 调用重载的构造器, 隐含调用了 super()
this(str);
this.num=num;
System.out.println("子类的有参构造 2");
}
}
publicclassConstructorTest{
publicstaticvoidmain(String[]args){
Sons1=newSon();
/*
父类的无参构造
子类的无参构造
*/
//Son s2 = new Son("java");
/*
父类的无参构造
子类的有参构造 1
*/
Sons3=newSon("java",10);
/*
父类的无参构造
子类的有参构造 1
子类的有参构造 2
*/
}
}
来源: http://www.bubuko.com/infodetail-3658642.html