06- 面向对象之封装 继承

本文详细探讨了Java面向对象的两大特性——封装和继承。封装旨在隐藏类的内部状态,防止外部直接访问,提高代码安全性。介绍了包的作用、访问权限修饰符以及static修饰符的使用。在继承部分,解释了如何通过继承实现代码重用,讨论了子类调用父类内容的规则,以及方法重写的基本概念和规则。同时,还涉及到Object类及其默认的equals()和toString()方法。

面向对象有三大特性 : 封装 继承 多态

封装

程序设计中遇到的问题

public class Student {
    String name;
    int age;
    String sex;
    String birthday;
}

测试类中引用

Student stu = new Student();
stu.name = "于志强";
stu.sex = "男";
stu.age = 2000;

程序设计的缺陷

外界可以随意的对对象的属性进行修改,赋值操作,没有任何约束

封装

实质是, 将类的状态隐藏在类内部, 不允许外部程序直接访问, 而是通过该类提供的方法来实现对隐藏信息的操作和访问

优势

  • 反映了事物的相对独立性, 有效地避免了外部错误对对象的影响
  • 隐藏类的实现细节,让使用者只能通过规定方式访问数据, 限制不合理操作

使用方式

private int age;
/**
 * 给age 创建相对应的方法
 * 通过方法内部的逻辑 来限制外界的访问
 */
public void setAge(int age){
    // 如果年龄在 0-127岁之间可以赋值
    if(age > 0 && age < 127){
        this.age = age;
    }else{
        System.out.println("年龄设置有误!");
     }
}
public int getAge(){
    return age;
}

举个栗子

想见明星

先和经纪人 预约, 经纪人条件列出来给你,出场费一百万

包结构

包的作用

  • 包可以将类组成较小的单元 (类似于文件夹)
  • 防止命名冲突 (学生 中学生middle 大学生college)
  • 允许制定规则在更广的范围内保护类,数据和方法

语法标准

// 声明 必须位于 java源文件的第一条非注释语句
package 包结构;

包结构通用规范

  • 一个唯一的包,前缀通常是小写的ASCII 字母, 并且是一个顶级域名,(com,cn,edu,gov,net,org)通常使用组织的网络域名的逆序 (cn.bdqn)
  • 域名.公司名.项目名.项目模块名

使用包结构

import college.Student;

回忆使用Scanner 类

import java.util.Scanner;

访问权限修饰符

包结构是一种访问控制机制,可以通过包限制和制约类之间的访问关系

类的访问修饰符

修饰符同一个包不同包
public可以使用可以使用
默认的可以使用不可以使用

类成员的修饰符

修饰符同一个类中同一包中子类不同包
public (公共的)
protected (受保护的)×
默认××
private(私有的)×××

static 修饰符

概念

static 含义 静态的 表示一个类中的属性或者方法是被该类的所有对象所共享

举个栗子

学生是一个类

个性: 学生的姓名, 年龄都是属于一个学生的特性

共性: 大家同处于一个教室 , 教室是属于大家的, 不是属于某一个学生的

该属性 是公共的 不单独属于某一个对象,而是属于所有对象
因为对象 都是从类中实例化出来的(类是一个模板,对象是基于该模板的一个实例)
静态属于所有对象, 静态是属于类的 属于模板的
教室中有饮水机 , 所有学生都可以使用, 但是没有所有权,只有使用权

静态属性的调用

public class Student {
    static String classRoom = "公用机房";
    String name;
}

Student stu1 = new Student();
stu1.name = "张三";
System.out.println(stu1.classRoom);

Student stu2 = new Student();
stu2.name = "李四";
System.out.println(stu2.classRoom);

使用对象调用静态 是不推荐的, 最好方式是使用类名调用

Student.classRoom

学习静态static之前

成员属性
成员方法

构造方法

成员代码块

在这里插入图片描述

学习静态static之后

成员属性

成员方法

成员代码块

静态属性

静态方法

静态代码块

构造方法

在这里插入图片描述

静态和非静态的执行顺序

静态 > 非静态
非静态 依赖于对象而存在的, 没有对象就没有非静态的属性
	学生的姓名 是非静态, 如果没有学生对象就没有姓名
静态 依赖于类存在,不依赖对象, 跟随类的加载而加载
	教室 即使没有开学, 没有一个学生, 教室依然存在
// 在没有创建任何对象的时候, 就可以使用 classRoom 属性
System.out.println(Student.classRoom);
// 如果想要使用非静态name属性 必须创建对象
Student stu = new Student();
stu.name = "张三";
System.out.println(stu.name);

类变量和实例变量的对比

类变量(静态变量)
    被static修饰的变量
    在内存中只有一个拷贝
    类内部,可在任何方法内直接访问静态变量
    其他类中,可以直接通过类名访问
实例变量
    没有被static修饰的变量
    每创建一个实例,就会为实例变量分配一次内存,实例变量可以在内存中有多个拷贝,互不影响

在这里插入图片描述

程序运行流程

  1. 静态属性
  2. 静态代码块
  3. 成员属性
  4. 构造代码块
  5. 构造方法

静态代码只会加载一次 , 静态内容在内存中只有一份

非静态, 每一次创建对象都会被运行一次

静态和非静态之间的相互调用

非静态可以使用 静态方法和静态属性

静态方法不可以使用非静态属性和非静态方法 包括this关键字

public class Student {
    static String classRoom = "公用机房";
    // 依赖于某个具体对象的 没有一个存在的学生, 就没有学生姓名
    String name;

    public void study(){
        // 不会产生冲突问题
        System.out.println(name +"在"+classRoom+"学习");
    }
    // 静态方法 可以直接使用类名来调用 , 不依赖于某一个具体对象
    public static void abc(){
        // name 依赖于某个具体对象的 没有一个存在的学生, 就没有学生姓名
        // 冲突问题
        System.out.println(name +"在"+classRoom+"学习");
    }
}

案例

模拟实现选民投票过程:一群选民进行投票,每个选民只允许投一次票,并且当投票总数达到100时,就停止投票
投票次数 属于选民的, 属于所有选民,而不是某一个选民

继承

书写两个类

猫狗案例 , 有很多相同的属性 方法

抽取类之间的共性, 成为父类(动物)

继承的语法

子类 extends 父类 (is a 是一个 的关系)

public class Animal {
    String type;
    String name;
    String sex;
    int age;

    public void sleep(){}
    public void eat(){}
}
public class Dog extends Animal{
    public void lookDoor(){}
}
public class Cat extends Animal{
    public void catchMouse(){}
}

特性

继承是Java中实现代码重用的重要手段之一。

Java中只支持单根继承,即一个类只能有一个直接父类

子类继承父类, 继承了父类所有非私有的属性和方法

子类调用父类的内容

语法

// 调用父类属性
super.name
// 调用父类的方法
super.eat();
// 调用父类的构造
super();
super(name);

注意点

super 只能出现在子类的方法和构造方法中

super 调用构造方法时,只能是第一句

super 不能访问父类的private成员

继承条件下的构造方法

1- 创建子类对象 默认去调用 父类的无参构造
2- 子类继承父类, 拥有了父类的所有的非私有属性, 子类就可以对这些属性进行操作
3- 构造方法就是给属性进行初始化的 , 子类构造方法没有通过super显式调用父类的有参构造方法,也没通过this显式调用自身其他构造方法 , 系统默认调用父类的无参构造方法

4- 子类构造方法通过super显式调用父类的有参构造方法, 执行父类相应构造方法,而不执行父类无参构造方法

子父类之间代码执行流程

在有继承关系的两个类, 代码中的内容是如何执行的

class Father{
    属性
    构造代码块
    构造方法
}
class Son extends Father{
    属性
    构造代码块
    构造方法
}

流程

父类的 属性 > 构造代码块 > 构造方法

子类的 属性 > 构造代码块 > 构造方法

在有静态内容加入的情况下

class Father{
	静态属性
    静态构造代码块
    属性
    构造代码块
    构造方法
}
class Son extends Father{
    静态属性
    静态构造代码块
    构造方法
}

1- 父类的静态属性, 静态代码块

2- 子类的静态属性, 静态代码块

3- 父类的成员属性,成员代码块, 构造方法

4- 子类的成员属性,成员代码块, 构造方法

子类不能获取父类的哪些资源

  • private成员
  • 子类与父类不在同包 , 使用默认访问权限的成员
  • 构造方法

方法重写

概念 :

子类根据需求对从父类继承的方法进行重新编写

重写时,可以用super.方法的方式来保留父类的方法

构造方法不能被重写 (子类不能继承父类的构造方法)

方法重写的规则

方法重写(override): 发生在两个有继承关系的类中, 子类重写继承自父类的方法, 要求方法名,参数列表,返回值一致, 访问修饰符权限不能低于父类,抛出异常不能高于父类

方法重载(overload): 发生在同一个类中, 方法名相同,参数列表不同,与访问修饰符,返回值类型无关

  1. 方法名相同
  2. 参数列表相同
  3. 返回值相同或是其子类
  4. 访问修饰符权限不能低于父类
  5. 抛出异常不能高于父类

在这里插入图片描述

Object 类

默认是所有类的父类

一个类如果不写 extends 默认继承Object类

Object(超类) 中国人 是炎黄子孙, 龙的传人

在这里插入图片描述

toString()

A a = new A("李四",20);
//  System.out.println(a.toString());  // date0710.A@1b6d3586
// 对象是在堆内存中保存的, 都拥有一个地址信息 1b6d3586 十六进制的地址表示方式
// 如果用户不希望看到类似于 date0710.A@1b6d3586 打印效果, 可以重写该方法
System.out.println(a); // 默认去调用 该对象的 toString()方法

equals()

== 比较运算符

如果比较的是两个基本数据类型 含义是直接比较值的大小

如果比较的是两个引用数据类型 含义是比较两个对象是否是同一对象

Object中 equals()方法 源码

public boolean equals(Object obj) {
    return (this == obj);
}

案例

public class Student {
    int sId;
    String name;

    public Student(){}
    public Student(int sId,String name){
        this.sId = sId;
        this.name = name;
    }

    @Override
    public boolean equals(Object obj) {
        // 强转类型
        Student stu = (Student)obj;

        return this.sId == stu.sId;
    }
}

public static void main(String[] args) {
    Student s1 = new Student(10086,"张三");
    Student s2 = new Student(10086,"张三");
    // 两名学生 学号一致 就是同一个人
    System.out.println(s1.equals(s2));   // 使用父类的 equals  s1 == s2
}

含义

Object 中的方法, 用于比较两个对象的地址是否相同, 一般要求子类重写, 用于比较两个对象的内容是否一致

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值