【JavaSE 第九天】

【JavaSE 第九天】

一、 复习回顾

1. 封装

(1) 封装

含义:

  • 将对象功能的实现细节隐藏,对外暴露公共的使用方式
    好处:
  • 安全性提高
  • 提高程序的扩展性
  • 代码复用性
(2) 程序中的封装体现

private 私有的,只是封装形式的一种体现

  • private 修饰符,只能本类访问
  • 只能修饰成员,成员方法,成员变量(属性)
  • 程序中,成员变量都要使用 private 修饰 (语法规范)
  • 提供方法 get(取值) / set (赋值)间接使用成员变量

2. 方法参数

(1) 方法的参数是基本数据类型
  • 方法的参数是基本数据类型,byte 、short 、int 、long 、float 、double 、char 、boolean
  • 方法参数是基本类型时,传递的是基本类型的具体数值
(2) 方法的参数是引用数据类型
  • 方法的参数是引用数据类型,数组
  • 引用数据类型中,方法参数传递的是内存中的地址值

二、 继承

1. 程序中的继承

在程序中也能出现继承的关系,让一个类继承另一个类
例如:A 类继承 B 类

  • 出现继承的关系
  • A 类是 B 类的子类,或者称为派生类
  • B 类是 A 类的父类,或者称为 超类 、基类
  • 子类可以直接拥有父类的成员(不是全部)

2. 继承的语法格式

继承使用关键字 extends ,用来表示继承的意思
(extend 本身含义是,扩展,延伸)

  • 定义格式
class B{}
class A extends B{} // A类继承 B类

父类:

public class Manager {
    String name;
    int age;
}

子类:

public class Teacher extends Manager{

}

调用:

    public static void main(String[] args) {
        /**
         *  创建对象:Manager的子类对象
         */
        Teacher teacher=new Teacher();
        // teacher对象,调用成员变量
        // teacher子类对象调用继承的成员变量
        teacher.name="张三";
        teacher.age=52;
        System.out.println("teacher.name = " + teacher.name);
        System.out.println("teacher.age = " + teacher.age);
    }

3. 继承的好处

使用程序中的继承,使用继承的好处:

  • 减少代码量
  • 复用性提高
  • 继承的存在导致了面向对象的最后一个特征:多态

继承的弊端:类和类之间的紧密性(依赖性)更强(扩展性更差)

三、 继承后各成员特点

1. 继承后成员变量的特点

子类和父类的成员变量同名的情况:

  • 调用的使用:子类自己有,使用自己的,子类没有,使用父类
    父类:
public class Fu {
    String s="父类";
}

子类:

public class Zi extends Fu{
    String s="子类";
}

调用:

    public static void main(String[] args) {
        // 创建子类对象
        Zi zi=new Zi();
        // 子类对象,调用变量
        System.out.println("zi.s = " + zi.s);
    }

2. super 关键字

super 关键字是超级的意思,在子类中调用父类的成员,使用此关键字

  • super.变量 调用父类的成员变量
  • super.方法 调用父类的成员方法
  • this 表示当前调用者对象(不是本类对象)
  • super 表示父类在内存中的存储空间(不是父类对象)
  • 方法中的局部变量与类中的成员变量同名的情况:
  • 在方法内部 用 this. 区分成员变量和局部变量
  • 在方法内部 用 super. 调用父类的成员变量
public class Zi extends Fu{
    String s="子类";
    public void print(){
        String s="方法";
        System.out.println("s = " + s);
        // 在方法内部 用 this. 区分成员变量和局部变量
        System.out.println("this.s = " + this.s);
        // 在方法内部 用 super. 调用父类的成员变量
        System.out.println("super.s = " + super.s); 
    }
}

3. 内存分析

  • 内存空间:
    • JDK 1.8 以后叫做 元数据区(Meta Data)
    • JDK 1.7 叫做 方法区
      内存分析

4. 继承后成员方法的特点

  • 方法重写(override):子类父类中出现了一模一样(方法的声明)的方法,称为子类重写了父类的方法,又称为覆盖或者叫做复写。(与重载不同)
  • 重写与重载的区别
    • 重写:
      重写(Override)是父类与子类之间多态性的一种表现。如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写 (Override)。子类的对象使用这个方法时,将调用子类中的定义,对它而言,父类中的定义如同被“屏蔽”了。
    • 重载:
      重载(Overload)是一个类中多态性的一种表现。如果在一个类中定义了多个同名的方法,它们参数列表不同,则称为方法的重载。
      区别:重载实现于一个类中、重写实现于子类中。
      调用子类重写的方法,假如子类没有重写,调用父类的方法
// 父类
public class Fu {
    public void print(){
        System.out.println("父类方法print");
    }
}
//子类
public class Zi extends Fu {
    /**
     * 重写父类的方法
     */
    public void print(){
        System.out.println("子类方法print:重写");
    }
}
//调用
    public static void main(String[] args) {
        //创建子类对象
        Zi zi = new Zi();
        zi.print();
    }

5. 方法重写的意义

继承的本质是扩展、延伸的意思,依靠方法的重写来实现

示例:
早期的(父类):

public class Phone {
    /**
     *  定义手机的来电显示功能
     *  数字移动电话
     */
    public void showingCall(){
        System.out.println("来电显示号码:");
    }
}

之后的(子类):

public class Iphone extends Phone{
    /**
     * 新手机
     * 功能变强,但是原有的功能不变,继续复用
     */
    // 重写父类的方法
    public void showingCall(){
        // 复用显示号码的功能,父类的方法中已经完成
        // 方法名不变,用户不需要重新认知
        // 调用父类的方法
        super.showingCall();
        // 新增的功能
        System.out.println("显示大头像");
        System.out.println("显示归属地");
    }
}

调用:

    public static void main(String[] args) {
        // 创建手机对象
        Phone phone=new Phone();
        System.out.println("第一个调用");
        phone.showingCall();
        // 创建新手机对象
        Iphone iphone=new Iphone();
        System.out.println("第二个调用");
        iphone.showingCall();
    }

6. 方法重写的问题

  • 方法重写需要考虑权限问题:
    保证子类的权限要大于或者等于父类的方法权限
    Alt + (Fn)+ Insert 快捷键 可以进行重写方法
  1. 父类的方法权限是 public

父类:

class Fu{
    public void print(){}
}

子类:

class Zi extends Fu{
    public void print(){} // 正确
    protected void print(){} // 错误,权限降低
    // 用 javac 编译会出现:“无法重写方法,正在尝试分配更低的访问权限”
    void print(){} // 错误,权限降低
    private void print(){} // 错误,权限降低
}
  1. 父类的方法权限是 protected

父类:

class Fu{
    protected void print(){}
}

子类:

class Zi extends Fu{
    public void print(){} // 正确
    protected void print(){} // 正确
    void print(){} // 错误,权限降低
    private void print(){} // 错误,权限降低
}
  1. 父类的方法权限是默认(缺省)

父类:

class Fu{
     void print(){}
}

子类:

class Zi extends Fu{
    public void print(){} //正确
    protected void print(){} //正确
    void print(){} //正确
    private void print(){} //错误,权限降低
}
  1. 如果父类的方法权限是 private,子类不知道该方法的存在,没有继承的说法。(不存在重写)
    这时四个写法都会正确,但并不是方法重写。

7. 继承后构造方法(构造器)特点

  • 构造方法特点 : 子类的构造方法(构造器)中,第一行存在隐式代码(写不写都存在),代码是 super();,作用是调用父类的无参数构造方法(构造器)。
  • 并且 super(); 与后续的代码不能换位置,必须在构造方法(构造器)的第一行。(实际上 Java 以“分号”区分作为“一行”)

父类:

public class Fu {
    public Fu(){
        System.out.println("父类构造方法");
    }
}

子类:

public class Zi extends Fu{
    public Zi(){
        super(); // 调用父类的无参数构造方法(绝对性存在)隐式代码
        System.out.println("子类构造方法");
    }
}

调用:

    public static void main(String[] args) {
        // 创建子类对象
        new Zi();
    }

内存分析:
内存分析

  • 补充:实际上 父类也是继承自 Object 类(Java中自己的类)
public class Fu extends Object{
    public Fu(){
        super();
        System.out.println("父类构造方法");
    }
}
  • 注意事项:
  1. 子类的构造方法,无论重载多少个,第一行肯定也是 super();
public class Zi extends Fu {
    public Zi(){
        super(); // 调用父类的无参数构造方法.
        System.out.println("子类构造方法");
    }

    public Zi(int a){
        super(); // 调用父类的无参数构造方法.
        System.out.println("子类构造方法:重载");
    }
}
  1. 父类中没有无参数构造方法(自己显式定义了新的构造方法,默认的隐式构造方法(无参的构造方法)消失),子类的构造方法中要用 super(传递参数); 因为父类中没有无参构造方法,所以要传递相应的参数,否则就会报错

父类:

public class Fu {
    public Fu(int a){
        // 父类的构造方法 加上参数,成为有参数的构造器
        System.out.println("父类构造方法" + a);
    }
}

子类:

public class Zi extends Fu{
    // 子类的无参构造方法
    public Zi(){
        // 父类中没有无参构造方法,调用有参的构造方法,传递相应的参数
        super(1); 
        System.out.println("子类构造方法");
    }
}
  1. 父类中存在多个构造方法,子类的构造方法只要调用到其中的一个即可(必须调用,至少一个)

父类:

public class Fu  {
    /**
     * 父类的构造方法
     * 加上参数,成为有参数的构造方法
     */
    public Fu(int a){
        System.out.println("父类构造方法" + a);
    }

    public Fu(String s){
        System.out.println("父类构造方法" + s);
    }
}

子类:

public class Zi extends Fu {
    // 子类的无参构造方法
    public Zi(){
        //父类中没有无参数构造
        //调用其中 int类型参数的传递相应的参数
        super(7);
    }
    // 子类的有参构造方法
    public Zi(String s){
        //调用父类构造方法,保证至少调用其中一个
        super("字符串");
    }
}

调用:

    public static void main(String[] args) {
        // 创建子类对象
        // new Zi(); 这是调用的是无参构造方法
        new Zi("1");  // 需要调用有参数的那个,保障传递运行
        // 保障能够调用运行即可
    }
  • 解释:
    1. 调用中的 “1” 传到了子类的有参构造方法中
    2. 子类把 “字符串” 这一参数传到了父类中的相应的构造方法中
    3. 输出结果。

四、 继承的特点

1. 单继承

  • 一个类只能继承一个类,不允许同时继承多个类
class A extends B,C{} // 不允许的行为,完全错误
  • 单继承存在局限性,为了解决局限性问题,引入了接口的概念

2. 多层继承

class A extends B{}
class B extends C{}
// 多层继承,允许实现
// class C extends Object{}  隐含项
  1. A 类可以同时拥有 B 和 C 的成员, B 只能拥有 C 的成员。
  2. A 类中 super 调用的是 B 类成员,如果 B 类没有成员,调用 C 成员。
  3. Object 类是 Java 中自己自带的类,所有的类都是 Object 的子类。
    注:这里的“成员"包含成员变量和成员方法。

3. 继承体系

  • 学习时:从继承体系的顶部学习(最具共性)
  • 使用时:使用时从最底层的部分使用(最具全面性)
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值