【JAVA】06 封装、继承、多态 总结(初级)

教程:B站韩顺平

一、访问修饰符

在这里插入图片描述

二、封装

  1. 将属性进行私有化【不能直接修改属性】
  2. 提供一个公共的set方法,用于对属性判断并赋值
  3. 提供一个公共的fet方法,用于获取属性的值

tips:将有防护功能的方法写在构造器中,也可以实现防护属性

三、继承

3.1 继承

继承可以解决代码复用,当多个类存在相同属性(变量)和方法时,可以从种抽取父类,在父类中重新定义这些相同的属性和方法,所有的子类不需要重新定义这些属性和方法,只需要通过extends继承即可

3.1.1 super关键字

  1. super表示父类的引用,用于访问父类的属性,方法,构造器

  2. 基本语法

    • 访问父类的属性,不能访问父类的private属性
      super.属性名
      
    • 访问父类的方法,不能访问父类的private方法
      super.方法名(参数列表);
      
  3. 访问父类的构造器:super(参数列表只能放在构造器的第一句,只能出现一句!)
    student.java

    public class student {
    		    private String name;
    		    private int age;
    		    public student(){}
    		    public student(String name, int age){
    		        setName(name);
    		        setAge(age);
    		    }
    		
    		    public void setName(String name) {
    		        this.name = name;
    		    }
    		
    		    public void setAge(int age) {
    		        this.age = age;
    		    }
    		
    		    public String getName() {
    		        return name;
    		    }
    		
    		    public int getAge() {
    		        return age;
    		    }
    		}
    

    pupil.java

    public class pupil extends student{
    				    private double grades;
    				
    				    public pupil(){}
    				
    				    public pupil(String name, int age,double grades){
    				        super(name,age);
    				        setGrades(grades);
    				    }
    				
    				    public void setGrades(double grades) {
    				        this.grades = grades;
    				    }
    				
    				    public double getGrades() {
    				        return grades;
    				    }
    				}
    

    testing.java

    public class testing {
    	    public static void main(String[] args) {
    	        pupil p = new pupil("小明",18,100.00);
    	        System.out.printf("name:%s,\tage:%d,\tgrades:%.2f",p.getName(),p.getAge(),p.getGrades());
    	    }
    	}
    

    在这里插入图片描述

  4. 调用方法的顺序:

    1. 先找本类,如果有,则调用

    2. 如果没有,则找父类,并可以调用,则调用

    3. 如果父类没有,则继续找父类的父类,整个规则相同,直到Object类

    4. tips:
      a. 如果查找方法的过程中,找到了,但是不能访问,则报错
      b. 如果查找方法的过程中,没有找到,则提示方法不存在
      c. super.cal()是直接查找父类,其他规则一样(从b步骤开始)
      d. 当子类中有和父类中的成员(属性和方法)重名是,为了访问父类的成员,必须通过super,如果没有重名,使用super、this、直接访问时一样的效果
      e. super的访问不限于直接父类,如果爷爷类和本类中有同名的成员,也可以使用super取访问爷爷类的成员,如果多个基类含有相同的属性名,则使用super访问遵循就近原则,A——>B——>C,同时也需要遵守访问权限的相关规则

    5. super和this的比较
      在这里插入图片描述

3.2 继承

3.2.1 概念

  1. 子类继承了所有类的属性和方法,非私有属性和方法可以在子类中直接访问,但是私有属性不能再子类直接访问,要通过公共的方法访问
  2. 子类必须调用父类的构造器,完成父类的初始化
  3. 当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会调用父类的无参构造器
  4. 如果父类没有提供无参构造器,则必须在子类的构造器中使用super去指定使用父类的哪个构造器完成对父类的初始化工作,否则编译不通过
  5. 如果希望指定去调用父类的某个构造器,则显式的调用一下
  6. super在使用时,需要放在构造器第一行
  7. super和this都只能放在构造器第一行,因为这两个方法不能共存在同一个构造器中
  8. java所有类都是Object类的子类,Object是所有类的基类
  9. 父类构造器的调用不限于直接父类,将一直往上追溯直到Object类(顶级父类)
  10. 子类最多只能继承一个父类(指直接继承),即java中是单继承方式
  11. 不能滥用继承,子类和父类之间必须满足is-a的逻辑关系

3.2.2 继承的本质

当子类对象创建好后,建立查找的关系

public class ExtendsTheory{
    public static void main(Strings[] agrs]){
        Son son = new Son();    
    }
}
class GrandPa{
    String name = "爷爷";
    String hobby = "旅游";
}
class Father extends GrandPa{
    String name = "爸爸";
    int age = 39;
}
class Son extends Father{
    String name = "儿子";
}

在这里插入图片描述

  • 由于只创建一个Son对象,故堆中只划分了一块区域
  • 然后再在方法区创建按照 Object——>Son的顺序创建对象
  • 调用方法时按照 本类——>Object的顺序进行查找(继承的顺序)

3.2.3 方法重写/覆盖

  1. 子类方法的形参列表,方法名要和父类的一样
  2. 子类方法的返回类型和父类方法返回类型一样,或者是父类返回类型的子类
    eg:父类:返回类型Object
    子类:返回类型String
  3. 子类方法不能缩小父类方法的访问权限:public>protected>默认>private
3.2.3.1 方法重载和方法重写的比较

在这里插入图片描述

四、多态

4.1 方法的多态

重写+重载

4.2 对象的多态

  1. 一个对象的编译类型和运行类型可以不一致

  2. 编译类型在定义对象时就确定了,不能改变

  3. 运行类型是可以变化的

  4. 编译时类型由声明该变量时使用的类型决定,编译时引用变量只能调用其编译类型所具有的方法。

  5. 运行时类型由实际赋给该变量的对象决定。

  6. 编译类型看定义时=的左边,运行类型看=的右边

    //Animal.java
    public class Animal {
        private String name;
        public Animal(){}
        public void cry(){
            System.out.println("cyr:animal");
        }
    }
    //Dog.java
    public class Dog extends Animal{
        public void cry() {
            System.out.println("cry dog");
        }
    }
    //Cat.java
    public class Cat extends Animal{
        public void cry(){
            System.out.println("cry: cat");
        }
    }
    //PolyObject.java
    public class PolyObject {
        public static void main(String[] args){
            Animal animal = new Dog(); //编译类型:Animal,运行类型Dog
            animal.cry();
            animal = new Cat();//编译类型:Animal,运行类型cat
            animal.cry();
        }
    }
    

    运行结果:
    在这里插入图片描述

  7. 案例

    //Animal.java
    public class Animal {
        private String name;
        public Animal(String name){
            this.name=name;
        }
        public String getName(){
            return this.name;
        }
    }
    //Dog.java
    public class Dog extends Animal{
        public Dog(String name){
            super(name);
        }
        public void cry() {
            System.out.println("cry dog:"+this.getName());
        }
    }
    //Food.java
    public class Food {
        private String name;
        public Food(String name){this.name=name;}
        public String getName(){
            return this.name;
        }
    }
    //Rice.java
    public class Rice extends Food{
        public Rice(String name){
            super(name);
        }
    }
    //PolyObject.java
    public class PolyObject {
        public static void main(String[] args){
            Animal animal = new Dog("大黄");
            animal.cry();
            Food food = new Rice("黑米粥");
            Master master = new Master("杰西");
            master.feed(animal,food);
        }
    }
    

4.3 向上转型

  1. 前提:两个对象(类)存在继承关系

  2. 本质:父类的引用指向了子类的对象

  3. 语法:父类类型

    引用名=new 子类类型()
    Animal animal = new Dog();
    
  4. 特点:编译类型看左边,运行类型看右边

  5. 可以调用父类中的所有成员(需要遵循访问权限)

  6. 不能调用子类中特有成员

  7. 最终运行效果看子类的具体实现(即运行时,按照运行类型决定)
    在这里插入图片描述

4.4 向下转型

  1. 语法:子类类型

    引用名 = (子类类型)父类引用;
    Cat cat = (Cat) animal; //但是要父类的引用必须是指向当前目标类型的引用
    
  2. 只能强转父类的引用,不能强转父类的对象

  3. 要求父类的引用必须指向的是当前目标类型的对象
    在这里插入图片描述

  4. 可以调用子类类型中的所有成员

4.5 多态——属性

属性没有重写之说,属性的值看编译类型

4.6 多态——instanceOf

instanceOf比较操作符,用于判断对象的运行类型 是否为xx类型 或者 xx类型的子类型

4.7 动态绑定机制❤️

  • 当调用对象方法时,该方法会和该对象的 内存地址/运行类型 绑定
  • 当调用对象属性时,没有动态绑定机制,哪里声明,哪里使用
    在这里插入图片描述
    在这里插入图片描述

4.8 应用

4.8.1 多态数组

例1:

public class PolyArray {
    public static void main(String[] args){
        Person[] persons = new Person[5];
        persons[0] = new Student("小明",100);
        persons[1] = new Student("大明",400);
        persons[2] = new Teacher("大强",20000);
        persons[3] = new Teacher("小强",50000);
        persons[4] = new Teacher("中强",90000);
        for(int i=0;i<persons.length;i++){
            persons[i].say();
            if(persons[i] instanceof Student){
                ((Student) persons[i]).study();
            }else if(persons[i] instanceof  Teacher){
                ((Teacher) persons[i]).teach();
            }else{
                System.out.println("类型错误");
            }
        }
    }
}
class Person {
    private String name;
    public Person(String name){
        this.name=name;
    }
    public String getName() {
        return this.name;
    }
    public void say(){
        System.out.println(this.name);
    }
}
class Student extends Person{
    private double grades;
    public Student(String name,double grades){
        super(name);
        this.grades = grades;
    }

    public double getGrades() {
        return grades;
    }

    public void say(){
        System.out.println("学生"+this.getName()+"成绩"+this.getGrades());
    }

    public void study(){
        System.out.println("学生"+this.getName()+"正在学习");
    }
}
class Teacher extends Person{
    private double salary;
    public Teacher(String name,double salary){
        super(name);
        this.salary = salary;
    }

    public double getSalary() {
        return salary;
    }
    public void say(){
        System.out.println("教师"+this.getName()+"薪酬"+this.getSalary());
    }
    public void teach(){
        System.out.println("教师"+this.getName()+"正在教书");
    }
}

4.8.2 例题

//Employee.java
public class Employee {
    private String name;
    private double salary;
    public Employee(String name, double salary){
        this.name=name;
        this.salary=salary;
    }
    public String getName() {
        return name;
    }
    public double getSalary() {
        return salary;
    }
    public double getAnnual(){
        return this.salary*12;
    }
}

//CommenEmployee.java
public class CommenEmployee extends Employee{
    public CommenEmployee(String name, double salary){
        super(name,salary);
    }
    public void work(){
        System.out.println("普通员工:"+super.getName()+"正在工作");
    }
}

//Manager.java
public class Manager extends Employee{
    private double bonus;
    public Manager(String name,double salary,double bonus){
        super(name,salary);
        this.bonus = bonus;
    }

    public double getBonus() {
        return bonus;
    }

    public void manage(){
        System.out.println("经理:"+super.getName()+"正在管理");
    }
}

//PolyParametersTesting.java
public class PolyParameterTesting {
    public void showEmpAnnual(Employee e){
        double salary = e.getSalary();
        if(e instanceof Manager){
            salary+=((Manager) e).getBonus();
        }
        System.out.println(salary);
    }
    public void testWork(Employee e){
        if(e instanceof CommenEmployee){
            ((CommenEmployee)e).work();
        }else if(e instanceof Manager){
            ((Manager)e).manage();
        }else {
            System.out.println("类型出错");
        }
    }
}

//PolyParameters.java
public class PolyParameter {
    public static void main(String[] args){
        Employee[] es = new Employee[2];
        es[0] = new CommenEmployee("员工",1000);
        es[1] = new Manager("经理",2000,500);
        PolyParameterTesting ppt = new PolyParameterTesting();
        for(int i=0;i<es.length;i++){
            ppt.showEmpAnnual(es[i]);
            ppt.testWork(es[i]);
        }
    }
}

五、Object类

5.1 == 和 equal

  1. ==:
  • 既可以判断基本类型,又可以判断引用类型
  • 如果判断基本类型,判断的是值是否相等
  • 如果判断引用类型,判断的是地址是否相等,即判断是否是同一个对象
  1. equals:
  • 是Object类中的方法,只能判断引用类型

  • 默认判断的是地址是否相等,子类中往往重写该方法,用于判断内容是否相等

    public boolean equals(Object obj){
        return (this ==obj);
    }
    
    public boolean equals(Object obj){
        if(obj instanceOf Integer){
            return value=((Integer)obj).intValue();    
        }
        return false;
    }
    

5.2 HashCode

  1. HashCode返回该对象的哈希码值,支持此方法是为了提高哈希表的性能
  2. 提高具有哈希结构的容器的效率
  3. 两个引用,如果指的是同一个对象,则哈希值肯定是一样的
  4. 两个引用,如果指向的不同对象,则哈希值是不一样的(但是也有可能一样:哈希碰撞)
  5. 哈希值主要是根据地址号来的!不能完全将哈希值等价于地址
  6. 在集合中,HashCode如果需要的话,也会重写

5.3 toString()

  1. 默认返回:全类名+@+哈希值的十六进制【查看Object的toString方法】

  2. 子类往往重写toString 方法,用于返回对象的属性信息

    public String toString(){
        return getClass().getName()+'@'+Integer.toHexString(hashCode());
    }
    
  3. 重写toString方法,打印对象或拼接对象时,都会自动调用该对象的toString形式

    public class Employee {
        private String name;
        private double salary;
        public Employee(String name, double salary){
            this.name=name;
            this.salary=salary;
        }
        public String toString(){
            return "Employee{" +
                    "name='"+name+'\'' +
                    "salary="+salary+'\''+
                    '}';
        }
    }
    
  4. 当直接输出一个对象时,toString方法会被默认的调用

5.4 finalize

  1. 当对象被回收是,系统自动调用该对象的finalize方法。子类可以重写该方法,做一些释放资源的操作:例如断开数据库链接,关闭文件等
  2. 如果程序员补充些finalize,则调用Object类的finalize,默认处理
  3. 如果重写finalze,则可以实现自己的逻辑
  4. 一般开发的时候不会重写finalize
  5. 什么时候被回收:当某个对象没有任何引用时,则jvm就认为这个对象是一个垃圾对象,就会使6用垃圾回收机制来销毁该对象,在销毁该对象前,会调用finalize方法
  6. 垃圾回收机制的调用,是由系统决定的,也可以使用System.gc()主动触发垃圾回收机制
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杰西啊杰西

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值