继承后的特点——成员变量

对象访问成员变量时,会先在子类中查找有没有定义对应的变量,若子类中存在就会就近使用子类中的变量,若子类中没有定义就会沿着继承关系往上找有没有定义相应的变量,若父类中也没有则编译不通过。代码示例:

class Fu {
// Fu类中的成员变量。
int num = 5;
int num2 = 7;
}
class Zi extends Fu {
// Zi类中的成员变量
int num = 6;
public void show() {
// 访问父类中的num2
System.out.println("num2=" + num2);
// 访问子类中的num
System.out.println("num=" + num);
}
}
public class ExtendsDemo0 {
public static void main(String[] args) {
// 创建子类对象
Zi z = new Zi();
// 调用子类中的show方法
z.show();
}
} 演示结果:
num2=7
num=6

子父类中出现了同名的成员变量时,在子类中访问父类中非私有成员变量,需要使用 super 关键字,用法类似于 this

使用格式:

super.父类成员变量名

代码如下:

class Zi extends Fu {
// Zi类中的成员变量
int num = 6;
public void show() {
//访问父类中的num
System.out.println("Fu num2=" + num2);
//访问父类中的num
System.out.println("Fu num=" + super.num);
}
}
演示结果:
Fu num = 7
Zi num = 5

Fu 类中的私有成员变量,子类是不能直接访问的。编码时,遵循封装的原则,使用private修饰成员变量,可以在父类中提供公共的getXxx方法和setXxx方法来访问。

super和this

父类空间优先于子类对象产生

在每次创建子类对象时,先初始化父类空间,再创建其子类对象本身。目的在于子类对象中包含了其对应的父类空间,便可以包含其父类的成员。代码体现在子类的构造方法调用时,一定先调用父类的构造方法。理解图解如下:

super和this的含义

  • super :代表父类的存储空间标识(可以理解为父类的引用)。

  • this :代表当前对象的引用(谁调用就代表谁)。

super和this的用法

this.成员变量 -- 本类的

super.成员变量 -- 父类的

this.成员方法名() -- 本类的

super.成员方法名() -- 父类的

代码示例:

class Animal {
public void eat() {
System.out.println("animal : eat");
}
} class Cat extends Animal {
public void eat() {
System.out.println("cat : eat");
}
public void eatTest() {
this.eat(); // this 调用本类的方法
super.eat(); // super 调用父类的方法
}
} public class ExtendsDemo08 {
public static void main(String[] args) {
Animal a = new Animal();
a.eat();
Cat c = new Cat();
c.eatTest();
}
} 输出结果为:
animal : eat
cat : eat
animal : eat

注意:

  1. 通过super引用属性、方法、构造器时,都要求该成员是可见的,即该成员的修饰符不能是private的,跨包的话还不能是缺省的。

  2. super的追溯不仅限于直接父类

  3. 如果某个属性或方法前面使用“this.”,那么先从本类中查找,如果未找到,会沿着继承关系往上找

    如果某个属性或方法前面使用“super.”,那么先从直接父类中查找,如果未找到,会沿着继承关系往上找

    如果某个属性或方法前面既没有“this.”,也没有“super.”,遵循就近原则,先从本类中查找,如果未找到,会沿着继承关系往上找

继承后的特点——成员方法

成员方法不重名时

如果子、父类中的方法不重名,这时的调用是没有影响的。对象调用方法时,会先在子类中查找有没有定义对应的方法,若子类中存在就执行子类中定义的方法,若子类中没有定义就会沿着继承关系往上找有没有定义相应的方法,若父类中也没有则编译不通过。代码示例:

class Fu{
public void show(){
System.out.println("Fu类中的show方法执行");
}
}
class Zi extends Fu{
public void show2(){
System.out.println("Zi类中的show2方法执行");
}
}
public class ExtendsDemo04{
public static void main(String[] args) {
Zi z = new Zi();
//子类中没有定义show方法,但是可以找从父类继承的show方法去执行
z.show();
z.show2();
}
}

成员方法重名——重写(Override)

如果子、父类中出现重名的成员方法,这时的访问是一种特殊情况,叫做方法重写 (Override)。

  • 方法重写 :子类继承了父类,可以获得父类的成员变量和成员方法;可是当父类的某个方法不适合于子类本身的特征时,在子类中可以根据需要对从父类中继承来的方法进行改造,也称为方法的重写、覆写。在程序执行时,子类的方法将覆盖父类的方法。

代码如下:

class Fu {
public void show() {
System.out.println("Fu show");
}
}
class Zi extends Fu {
//子类重写了父类的show方法
public void show() {
System.out.println("Zi show");
}
}
public class ExtendsDemo05{
public static void main(String[] args) {
Zi z = new Zi();
// 子类中有show方法,只执行重写后的show方法
z.show(); // Zi show
}
}

重写的应用

子类可以根据需要,定义特定于自己的行为。既沿袭了父类的功能名称,又根据子类的需要重新实现父类方法,从而进行扩展增强。比如新的手机增加来电显示头像的功能,代码如下:

class Phone {
public void sendMessage(){
System.out.println("发短信");
}
public void call(){
System.out.println("打电话");
}
public void showNum(){
System.out.println("来电显示号码");
}
} //智能手机类
class NewPhone extends Phone { //重写父类的来电显示号码功能,并增加自己的显示姓名和图片功能
public void showNum(){
//调用父类已经存在的功能使用super
super.showNum();
//增加自己特有显示姓名和图片功能
System.out.println("显示来电姓名");
System.out.println("显示头像");
}
} public class ExtendsDemo06 {
public static void main(String[] args) {
// 创建子类对象
NewPhone np = new NewPhone(); // 调用父类继承而来的方法
np.call(); // 调用子类重写的方法
np.showNum(); }
}

重写时,用到super.父类成员方法,表示调用父类的成员方法。

方法重写注意事项

  1. 方法名:必须完全一致

  2. 形参列表:必须完全一致

  3. 返回值类型:

    如果是基本数据类型和void,必须一致

    如果是引用数据类型,重写的方法的返回值类型 <= 被重写方法的返回值类型,Student<Person

  4. 修饰符:重写的方法的修饰符范围 >= 被重写方法的修饰符范围(public > protected > 缺省 > private)

  5. 被重写方法不能被 privatestaticfinal 修饰,如果跨包的话,修饰符缺省的也不能被重写,因为缺省的跨包不可见

继承后的特点——构造方法

首先我们要回忆两个事情,构造方法的定义格式和作用:

  1. 构造方法的名字是与类名一致的。所以子类是无法继承父类构造方法的。
  2. 构造方法的作用是初始化成员变量的。所以子类的初始化过程中,必须先执行父类的初始化动作。
    • 子类不会继承父类的构造器,但是一定会调用父类的构造器
    • 默认情况下,调用的是父类的无参构造,super()写或不写都会调用父类的无参构造,如果要写,必须在子类构造器首行
    • 如果父类没有无参构造,必须在子类的构造器首行使用super(实参列表)显式调用父类的有参构造,否则编译报错
    • super([形参列表]) 和 this([形参列表]) 都必须是在构造方法的第一行,所以不能同时出现。

代码示例:

class Father{
public Father(){
System.out.println("父类的无参构造");
}
} class Son extends Father{
private String str;
private int num; public Son(){
//隐含调用了super(); 子类的构造器中一定会调用父类的构造器,默认调用父类的无参构造
System.out.println("子类的无参构造");
} public Son(String str){
//隐含调用了super()
this.str = str;
System.out.println("子类的有参构造1");
} public Son(String str,int num){
//调用重载的构造器,隐含调用了super()
this(str);
this.num = num;
System.out.println("子类的有参构造2");
}
} public class ConstructorTest {
public static void main(String[] args) {
Son s1 = new Son();
/*
父类的无参构造
子类的无参构造
*/
//Son s2 = new Son("java");
/*
父类的无参构造
子类的有参构造1
*/ Son s3 = new Son("java", 10);
/*
父类的无参构造
子类的有参构造1
子类的有参构造2
*/
}
}

Java继承后访问成员的特点的更多相关文章

  1. java继承关系中成员变量,构造方法,成员方法的关系

    Java继承中的成员关系 A:成员变量 a:子类的成员变量名称和父类中的成员变量名称不一样,这个太简单写那个名字就访问那个名字! b:子类的成员变量名称和父类中的成员变量名称一样,这个怎么访问呢? 子 ...

  2. Java继承和访问修饰符

    继承 概念:为了提取两个类中公共代码,可以使用继承抽取重复性的代码到一个公共类中,这个公共的类称为父类(super class).继承于父类的类称为子类(sub class). 关键字     ext ...

  3. Java 访问限制符 在同一包中或在不同包中:使用类创建对象的权限 & 对象访问成员变量与方法的权限 & 继承的权限 & 深入理解protected权限

    一.实例成员与类成员 1. 当类的字节码被加载到内存, 类中类变量.类方法即被分配了相应内存空间.入口地址(所有对象共享). 2. 当该类创建对象后,类中实例变量被分配内存(不同对象的实例变量互不相同 ...

  4. C++入门经典-类成员的可访问性,继承后的可访问性

    1:关键字public.private.protected说明类成员是共有的.私有的,还是保护的.这3个关键字将类划分为3个区域,在public区域的类成员可以在类作用域外被访问,而private区域 ...

  5. java 继承访问成员变量

    package java09; //创建父类 public class Fu { int numFu = 10; int num =100; public void methodFu(){ Syste ...

  6. java:包、继承,访问修饰符

    包 包(package) 用于管理程序中的类,主要用于解决类的同名问题.包可以看出目录. 包的作用 [1] 防止命名冲突. [2] 允许类组成一个单元(模块),便于管理和维护 [3] 更好的保护类.属 ...

  7. JAVA知识总结(三):继承和访问修饰符

    今天乘着还有一些时间,把上次拖欠的面向对象编程三大特性中遗留的继承和多态给简单说明一下.这一部分还是非常重要的,需要仔细思考. 继承 继承:它是一种类与类之间的关系,通过使用已存在的类作为基础来建立新 ...

  8. C++继承后的函数访问权限

    今天在写代码时发现对继承后的函数访问权限不太清楚,于是自己做了个测试: 1.头文件(test.h) 1 #include <iostream>  2 using namespace std ...

  9. java中用反射访问私有方法和私有成员[转]

    转自: http://zhouyangchenrui.iteye.com/blog/470521 java的反射可以绕过访问权限,访问到类的私有方法和成员.可能这点会引起安全性的讨论.反射的使用帮助解 ...

随机推荐

  1. 题解 洛谷 P5311 【[Ynoi2011]成都七中】

    每次询问是关于 \(x\) 所在的连通块,所以考虑用点分树来解决本题. 点分树上每个节点所对应的子树,都是原树中的一个连通块.询问中给定 \(x\) 和区间 \([l,r]\),其就已经确定了原树的一 ...

  2. python-study-文件操作

    # 一.文件操作的作用 :读取内容.写入内容.备份内容.... # 文件的基本操作,文件操作包含:打开.关闭.读.写.复制.... # 打开 读写 关闭 # 文件备份 # 文件和文件夹的操作 # 总结 ...

  3. 主机无法访问虚拟机中运行的Django项目

    在虚拟机中的linux上运行了Django项目,虚拟机中可以访问,但外部主机无法访问(连接超时),但主机能ping同虚拟机,虚拟机也能ping通主机 需检查三个地方:(后面发现虚拟机的ip地址存在改变 ...

  4. pycharm控制台输出的日志全是红色的字体?

    问题:logging在pycharm控制台输出的日志的字体全是红色的,怎么办? 图片描述: 解决办法:设置 -> 搜索“Console” ->  结果:改完立马生效

  5. Python 正则表达式简单了解

    match 从字符串的开始匹配  如果开头不符合要求  就会报错 search  用字符串里的每一个元素  去匹配找的元素 1.匹配单个字符 \d 数字 \D 非数字 . 匹配任意字符 除了\n [] ...

  6. android 官方教程地址和一个中文教程

    https://developer.android.google.cn/guide/components/fundamentals http://www.runoob.com/w3cnote/andr ...

  7. front-end——HTML5/CSS3基础

    概述 1.什么是前端 前端即网站前台部分,运行在PC端,移动端等浏览器上展现给用户浏览的网页,随着互联网技术的发展,html5,css3,前端框架的应用,跨平台响应式网页设计能够适应各种屏幕分辨率,完 ...

  8. pandas之时间数据

    1.时间戳Timestamp() 参数可以为各种形式的时间,Timestamp()会将其转换为时间. time1 = pd.Timestamp('2019/7/13') time2 = pd.Time ...

  9. IO流——字节流、字符流

    在程序中所有的数据都是以流的方式进行传输或保存的,程序需要数据的时候要使用输入流读取数据,而当程序需要将一些数据保存起来的时候,就要使用输出流完成. 流的分类 ①   流按其流向分为“输入流”和“输出 ...

  10. PHP 函数实例讲解

    PHP 函数 PHP 的真正威力源自于它的函数. 在 PHP 中,提供了超过 1000 个内建的函数. PHP 内建函数 如需查看所有数组函数的完整参考手册和实例,请访问我们的 PHP 参考手册. P ...