面向对象编程(中级部分)

1 IDE(集成开发环境)-IDEA

1.1 IDEA 介绍

(1) IDEA 全称 IntelliJ IDEA
(2) 在业界被公认为最好的 Java 开发工具
(3) IDEA 是 JetBrains 公司的产品,总部位于捷克的首都布拉格
(4) 除了支持 Java 开发,还支持 HTML,CSS,PHP,MySQL,Python 等

2 IDE(集成开发环境)-Eclipse

2.1 Eclipse 介绍

(1) Eclipse 是一个开放源代码的、基于 Java 的可扩展开发平台。
(2) 最初是由 IBM 公司耗资 3000 万美金开发的下一代 IDE 开发环境
(3) 2001 年 11 月贡献给开源社区
(4) Eclipse 是目前最优秀的 Java 开发 IDE 之一

3 IDE(集成开发环境)-IDEA 的使用

在这里插入图片描述

3.1 IDEA 使用技巧和经验

设置字体 [如图] 和 颜色主题
菜单 file -> settings
在这里插入图片描述
字符编码设置
在这里插入图片描述
在这里插入图片描述

3.2 IDEA 常用快捷键

  1. 删除当前行, 默认是 ctrl + Y 自己配置 ctrl + d
  2. 复制当前行, 自己配置 ctrl + alt + 向下光标
  3. 补全代码 alt + /
  4. 添加注释和取消注释 ctrl + / 【第一次是添加注释,第二次是取消注释】
  5. 导入该行需要的类 先配置 auto import , 然后使用 alt+enter 即可
  6. 快速格式化代码 ctrl + alt + L
  7. 快速运行程序 自己定义 alt + R
  8. 生成构造器等 alt + insert [提高开发效率]
  9. 查看一个类的层级关系 ctrl + H [学习继承后,非常有用]
  10. 将光标放在一个方法上,输入 ctrl + B , 可以定位到方法 [学继承后,非常有用]
  11. 自动的分配变量名 , 通过 在后面假 .var [老师最喜欢的]

3.3 模板/自定义模板

在这里插入图片描述

4 包

4.1看一个应用场景

在这里插入图片描述

4.2包的三大作用

(1)区分相同名字的类
(2)当类很多时,可以很好的管理类【看Java API 文档】
(3)控制访问范围

4.3 包基本语法

在这里插入图片描述

4.4包的本质分析(原理)

在这里插入图片描述

4.5 包的命名

在这里插入图片描述

4.6 常用的包

一个包下,包含很多的类,java 中常用的包有:
(1) java.lang.* //lang 包是基本包,默认引入,不需要再引入. (2) java.util.* //util 包,系统提供的工具包, 工具类,使用 Scanner
(3) java.net.* //网络包,网络开发
(4) java.awt.* //是做 java 的界面开发,GUI

4.7 如何引入包

语法:import 包;
我们引入一个包的主要目的是使用该包下的类,比如 import java.util.Scanner;就只是引入一个类Scanner。import java.util.* ;//表示将java.util 包所有的类都引入

package com.hspedu.pkg;

import java.util.Arrays;

//注意:
//建议:我们需要使用到哪个类,就导入哪个类即可,不建议使用 *导入
//import java.util.Scanner; //表示只会引入java.util 包下的 Scanner
//import java.util.*;//表示将java.util 包下的所有类都引入(导入)
public class Import01 {
    
    

    public static void main(String[] args) {
    
    

        //使用系统提供 Arrays 完成 数组排序
        int[] arr = {
    
    -1, 20, 2, 13, 3};
        //比如对其进行排序
        //传统方法是,自己编写排序(冒泡)
        //系统是提供了相关的类,可以方便完成 Arrays
        Arrays.sort(arr);
        //输出排序结果
        for (int i = 0; i < arr.length ; i++) {
    
    
            System.out.print(arr[i] + "\t");
        }
    }
}

4.8注意事项和使用细节

(1)package 的作用是声明当前类所在的包,需要放在类的最上面,一个类中最多只有一句package
(2)import指令 位置放在package的下面,在类定义前面,可以有多句且没有顺序要求。

//package的作用是声明当前类所在的包,需要放在类(或者文件)的最上面,
// 一个类中最多只有一句package

package com.hspedu.pkg;

//import指令 位置放在package的下面,在类定义前面,可以有多句且没有顺序要求
import java.util.Scanner;
import java.util.Arrays;

//...

//类定义
public class PkgDetail {
    
    

    public static void main(String[] args) {
    
    
        Scanner scanner = new Scanner(System.in);
        int[] arr = {
    
    0, -1, 1};
        Arrays.sort(args);
    }
}



5 访问修饰符

5.1基本介绍

java 提供四种访问控制修饰符号,用于控制方法和属性(成员变量)的访问权限(范围):

  1. 公开级别:用 public 修饰,对外公开
  2. 受保护级别:用 protected 修饰,对子类和同一个包中的类公开
  3. 默认级别:没有修饰符号,向同一个包的类公开.
  4. 私有级别:用 private 修饰,只有类本身可以访问,不对外公开.

5.2 4种访问修饰符的访问范围

在这里插入图片描述

5.3 使用的注意事项

(1)修饰符可以用来修饰类中的属性,成员方法以及类
(2)只有默认的和public才能修饰类!并且遵循上述访问权限的特点
(3)因为没有学习继承,因此关于在子类中的访问权限,我们讲完子类后,在回头讲解
(4)成员方法的访问规则和属性完全一样。

6 面向对象编程三大特征

6.1 基本介绍

面向对象编程有三大特征:封装、继承和多态。

6.2 封装介绍

封装(encapsulation)就是把抽象出的数据【属性】和对数据的操作【方法】封装在一起。数据被保护在内部,程序的其他部分只有通过被授权的操作【方法】,才能对数据进行操作。

6.3封装的理解和好处

(1)隐藏实现细节:方法(连接数据库)<—调用(传入参数…)
(2)可以对数据进行验证,保证安全合理

6.4封装的实现步骤 (三步)

(1)将属性进行私有化private 【不能直接修改属性】
(2)提供一个公共的(public)set方法,用于对属性判断并赋值。

public void setXxx(类型 参数名){
    
    //Xxx 表示某个属性
		//加入数据验证的业务逻辑
		属性 = 参数名;
}

7 快速入门案例

请大家看一个小程序(com.hspedu.encap:Encapsulation01.java),
不能随便查看人的年龄,工资等隐私,并对设置的年龄进行合理的验证。年龄合理就设置,否则给默认年龄, 必须在 1-120, 年龄, 工资不能直接查看 , name的长度在 2-6字符之间

package com.hspedu.encap;

public class Encapsulation01 {
    
    

    public static void main(String[] args) {
    
    
        //如果要使用快捷键alt+r, 需要先配置主类
        //第一次,我们使用鼠标点击形式运算程序,后面就可以用
        Person person = new Person();
        person.setName("韩顺平");
        person.setAge(30);
        person.setSalary(30000);
        System.out.println(person.info());
        System.out.println(person.getSalary());

        //如果我们自己使用构造器指定属性
        Person smith = new Person("smith", 80, 50000);
        System.out.println("====smith的信息======");
        System.out.println(smith.info());


    }
}
/*
那么在java中如何实现这种类似的控制呢?
请大家看一个小程序(com.hspedu.encap: Encapsulation01.java),
不能随便查看人的年龄,工资等隐私,并对设置的年龄进行合理的验证。年龄合理就设置,否则给默认
年龄, 必须在 1-120, 年龄, 工资不能直接查看 , name的长度在 2-6字符 之间

 */
class Person {
    
    
    public  String name; //名字公开
    private int age; //age 私有化
    private double salary; //..

    public void say(int n,String name) {
    
    

    }
    //构造器 alt+insert
    public Person() {
    
    
    }
    //有三个属性的构造器
    public Person(String name, int age, double salary) {
    
    
//        this.name = name;
//        this.age = age;
//        this.salary = salary;
        //我们可以将set方法写在构造器中,这样仍然可以验证
        setName(name);
        setAge(age);
        setSalary(salary);
    }

    //自己写setXxx 和 getXxx 太慢,我们使用快捷键alt + insert
    //然后根据要求来完善我们的代码.
    public String getName() {
    
    
        return name;
    }
    public void setName(String name) {
    
    
        //加入对数据的校验,相当于增加了业务逻辑
        if(name.length() >= 2 && name.length() <=6 ) {
    
    
            this.name = name;
        }else {
    
    
            System.out.println("名字的长度不对,需要(2-6)个字符,默认名字");
            this.name = "无名人";
        }
    }

    public int getAge() {
    
    
        return age;
    }

    public void setAge(int age) {
    
    
        //判断
        if(age >= 1 && age <= 120) {
    
    //如果是合理范围
            this.age = age;
        } else {
    
    
            System.out.println("你设置年龄不对,需要在 (1-120), 给默认年龄18 ");
            this.age = 18;//给一个默认年龄
        }
    }

    public double getSalary() {
    
    
        //可以这里增加对当前对象的权限判断
        return salary;
    }

    public void setSalary(double salary) {
    
    
        this.salary = salary;
    }
    //写一个方法,返回属性信息
    public String info() {
    
    
        return "信息为 name=" + name  + " age=" + age + " 薪水=" + salary;
    }
}

7.1 将构造器和 setXxx 结合

看案例:

//有三个属性的构造器
public Person(String name, int age, double salary) {
    
    
	// this.name = name;
	// this.age = age;
	// this.salary = salary;
	//我们可以将 set 方法写在构造器中,这样仍然可以验证
	setName(name);
	setAge(age);
	setSalary(salary);
}

7.2 练习

在这里插入图片描述

package com.hspedu.encap;

/**
 * 创建程序,在其中定义两个类:Account和AccountTest类体会Java的封装性。
 * Account类要求具有属性:姓名(长度为2位3位或4位)、余额(必须>20)、
 * 密码(必须是六位), 如果不满足,则给出提示信息,并给默认值(程序员自己定)
 * 通过setXxx的方法给Account 的属性赋值。
 * 在AccountTest中测试
 */
public class Account {
    
    
    //为了封装,将3个属性设置为private
    private String name;
    private double balance;
    private String pwd;

    //提供两个构造器
    public Account() {
    
    
    }

    public Account(String name, double balance, String pwd) {
    
    
        this.setName(name);
        this.setBalance(balance);
        this.setPwd(pwd);
    }

    public String getName() {
    
    
        return name;
    }

    //姓名(长度为2位3位或4位)
    public void setName(String name) {
    
    
        if (name.length() >= 2 && name.length() <= 4) {
    
    
            this.name = name;
        } else {
    
    
            System.out.println("姓名要求(长度为2位3位或4位),默认值 无名");
            this.name = "无名";
        }
    }

    public double getBalance() {
    
    
        return balance;
    }

    //余额(必须>20)
    public void setBalance(double balance) {
    
    
        if (balance > 20) {
    
    
            this.balance = balance;
        } else {
    
    
            System.out.println("余额(必须>20) 默认为0");
        }
    }

    public String getPwd() {
    
    
        return pwd;
    }

    //密码(必须是六位)
    public void setPwd(String pwd) {
    
    
        if (pwd.length() == 6) {
    
    
            this.pwd = pwd;
        } else {
    
    
            System.out.println("密码(必须是六位)默认密码为 000000");
            this.pwd = "000000";
        }
    }
    //显示账号信息
    public void showInfo() {
    
    
        //可以增加权限的校验
        System.out.println("账号信息 name=" + name + " 余额=" + balance + " 密码" + pwd);
//        if() {
    
    
//            System.out.println("账号信息 name=" + name + " 余额=" + balance + " 密码");
//        }else{
    
    
//            System.out.println("你无权查看...");
//        }
    }
}

package com.hspedu.encap;

public class TestAccount {
    
    
    public static void main(String[] args) {
    
    
        //创建Account
        Account account = new Account();
        account.setName("jack");
        account.setBalance(60);
        account.setPwd("123456");

        account.showInfo();
    }
}

8 面向对象编程-继承

8.1为什么需要继承

在这里插入图片描述

package com.hspedu.extend_;

public class Extends01 {
    
    
    public static void main(String[] args) {
    
    
        Pupil pupil = new Pupil();
        pupil.name = "银角大王";
        pupil.age = 10;
        pupil.testing();
        pupil.setScore(60);
        pupil.showInfo();

        System.out.println("=======");
        Graduate graduate = new Graduate();
        graduate.name = "金角大王";
        graduate.age = 22;
        graduate.testing();
        graduate.setScore(100);
        graduate.showInfo();

    }
}

8.2 继承基本介绍和示意图

继承可以解决代码复用,让我们的编程更加靠近人类思维.当多个类存在相同的属性(变量)和方法时,可以从这些类中抽象出父类,在父类中定义这些相同的属性和方法,所有的子类不需要重新定义这些属性和方法,只需要通过 extends 来声明继承父类即可。继承的示意图
在这里插入图片描述

8.3 继承的基本语法

在这里插入图片描述

8.4 快速入门案例

package com.hspedu.extend_.improve_;

import com.hspedu.extend_.Graduate;
import com.hspedu.extend_.Pupil;

public class Extends01 {
    
    
    public static void main(String[] args) {
    
    
        com.hspedu.extend_.Pupil pupil = new Pupil();
        pupil.name = "银角大王~";
        pupil.age = 11;
        pupil.testing();
        pupil.setScore(50);
        pupil.showInfo();

        System.out.println("=======");
        com.hspedu.extend_.Graduate graduate = new Graduate();
        graduate.name = "金角大王~";
        graduate.age = 23;
        graduate.testing();
        graduate.setScore(80);
        graduate.showInfo();
    }
}

package com.hspedu.extend_.improve_;

//父类,是Pupil 和 Graduate的父类
public class Student {
    
    
    //共有属性
    public String name;
    public int age;
    private double score;//成绩
    //共有的方法
    public void setScore(double score) {
    
    
        this.score = score;
    }

    public void showInfo() {
    
    
        System.out.println("学生名 " + name + " 年龄 " + age + " 成绩 " + score);
    }
}

package com.hspedu.extend_.improve_;

//让Pupil 继承 Student类
public class Pupil extends Student {
    
    
    public void testing() {
    
    
        System.out.println("小学生 " + name + "  正在考小学数学..");
    }
}

package com.hspedu.extend_.improve_;

public class Graduate extends Student {
    
    

    public void testing() {
    
    //和Pupil不一样
        System.out.println("大学生 " + name + " 正在考大学数学..");
    }
}

8.5 继承给编程带来的便利

  1. 代码的复用性提高了
  2. 代码的扩展性和维护性提高了

8.6 继承的深入讨论/细节问题

  1. 子类继承了所有的属性和方法,非私有的属性和方法可以在子类直接访问, 但是私有属性和方法不能在子类直接访问,要通过父类提供公共的方法去访问
  2. 子类必须调用父类的构造器, 完成父类的初始化
  3. 当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器,如果父类没有提供无参构造器,则必须在子类的构造器中用 super 去指定使用父类的哪个构造器完成对父类的初始化工作,否则,编译不会通过(怎么理解。) [举例说明]
  4. 如果希望指定去调用父类的某个构造器,则显式的调用一下 : super(参数列表)
  5. super 在使用时,必须放在构造器第一行(super 只能在构造器中使用)
  6. super() 和 this() 都只能放在构造器第一行,因此这两个方法不能共存在一个构造器
  7. java 所有类都是 Object 类的子类, Object 是所有类的基类.
  8. 父类构造器的调用不限于直接父类!将一直往上追溯直到 Object 类(顶级父类)
  9. 子类最多只能继承一个父类(指直接继承),即 java 中是单继承机制。
    思考:如何让 A 类继承 B 类和 C 类? 【A 继承 B, B 继承 C】
  10. 不能滥用继承,子类和父类之间必须满足 is-a 的逻辑关系
package com.hspedu.extend_;

public class ExtendsDetail {
    
    
    public static void main(String[] args) {
    
    
//        System.out.println("===第1个对象====");
//        Sub sub = new Sub(); //创建了子类对象 sub
//        System.out.println("===第2个对象====");
//        Sub sub2 = new Sub("jack"); //创建了子类对象 sub2
        System.out.println("===第3对象====");
        Sub sub3 = new Sub("king", 10); //创建了子类对象 sub2
        //sub.sayOk();
    }
}

package com.hspedu.extend_;

public class Base extends TopBase {
    
     //父类
    //4个属性
    public int n1 = 100;
    protected int n2 = 200;
    int n3 = 300;
    private int n4 = 400;

    public Base() {
    
     //无参构造器
        System.out.println("父类Base()构造器被调用....");
    }
    public Base(String name, int age) {
    
    //有参构造器
        //默认super()
        System.out.println("父类Base(String name, int age)构造器被调用....");
    }
    public Base(String name) {
    
    //有参构造器
        System.out.println("父类Base(String name)构造器被调用....");
    }
    //父类提供一个public的方法,返回了n4
    public int getN4() {
    
    
        return n4;
    }
    public void test100() {
    
    
        System.out.println("test100");
    }
    protected void test200() {
    
    
        System.out.println("test200");
    }
    void test300() {
    
    
        System.out.println("test300");
    }
    private void test400() {
    
    
        System.out.println("test400");
    }
    //call
    public void callTest400() {
    
    
        test400();
    }
}


package com.hspedu.extend_;

import java.util.Arrays;

//输入ctrl + H 可以看到类的继承关系
public class Sub extends Base {
    
     //子类

    public Sub(String name, int age) {
    
    
        //1. 要调用父类的无参构造器, 如下或者 什么都不写,默认就是调用super()
        //super();//父类的无参构造器
        //2. 老师要调用父类的 Base(String name) 构造器
        //super("hsp");
        //3. 老师要调用父类的 Base(String name, int age) 构造器
        super("king", 20);

        //细节: super在使用时,必须放在构造器第一行
        //细节: super() 和 this() 都只能放在构造器第一行,因此这两个方法不能共存在一个构造器
        //this() 不能再使用了
        System.out.println("子类Sub(String name, int age)构造器被调用....");


    }

    public Sub() {
    
    //无参构造器
        //super(); //默认调用父类的无参构造器
        super("smith", 10);
        System.out.println("子类Sub()构造器被调用....");
    }
    //当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器
    public Sub(String name) {
    
    
        super("tom", 30);
        //do nothing...
        System.out.println("子类Sub(String name)构造器被调用....");
    }

    public void sayOk() {
    
    //子类方法
        //非私有的属性和方法可以在子类直接访问
        //但是私有属性和方法不能在子类直接访问
        System.out.println(n1 + " " + n2 + " " + n3);
        test100();
        test200();
        test300();
        //test400();错误
        //要通过父类提供公共的方法去访问
        System.out.println("n4=" + getN4());
        callTest400();//
    }

}

8.7 继承的本质分析(重要)

视频链接: https://www.bilibili.com/video/BV1fh411y7R8?p=294.

在这里插入图片描述

package com.hspedu.extend_;

/**
 * 讲解继承的本质
 */
public class ExtendsTheory {
    
    
    public static void main(String[] args) {
    
    
        Son son = new Son();//内存的布局
        //?-> 这时请大家注意,要按照查找关系来返回信息
        //(1) 首先看子类是否有该属性
        //(2) 如果子类有这个属性,并且可以访问,则返回信息
        //(3) 如果子类没有这个属性,就看父类有没有这个属性(如果父类有该属性,并且可以访问,就返回信息..)
        //(4) 如果父类没有就按照(3)的规则,继续找上级父类,直到Object...
        System.out.println(son.name);//返回就是大头儿子
        //System.out.println(son.age);//返回的就是39
        //System.out.println(son.getAge());//返回的就是39
        System.out.println(son.hobby);//返回的就是旅游
    }
}

class GrandPa {
    
     //爷类
    String name = "大头爷爷";
    String hobby = "旅游";
}

class Father extends GrandPa {
    
    //父类
    String name = "大头爸爸";
    private int age = 39;

    public int getAge() {
    
    
        return age;
    }
}

class Son extends Father {
    
     //子类
    String name = "大头儿子";
}


子类创建的内存布局:
在这里插入图片描述

8.8 练习

在这里插入图片描述
2) 案例 2 ExtendsExercise02.java

package com.hspedu.extend_.exercise;

public class ExtendsExercise02 {
    
    
    public static void main(String[] args) {
    
    
        C c = new C();
    }
}

class A {
    
    //A类

    public A() {
    
    
        System.out.println("我是A类");
    }
}

class B extends A {
    
     //B类,继承A类		//main方法中: C c =new C(); 输出么内容? 3min
    public B() {
    
    
        System.out.println("我是B类的无参构造");
    }

    public B(String name) {
    
    
        System.out.println(name + "我是B类的有参构造");
    }
}

class C extends B {
    
       //C类,继承 B类
    public C() {
    
    
        this("hello");
        System.out.println("我是c类的无参构造");
    }

    public C(String name) {
    
    
        super("hahah");
        System.out.println("我是c类的有参构造");
    }
}


  1. 案例 3 ExtendsExercise03.java
    (1)编写Computer类,包含CPU、内存、硬盘等属性,getDetails方法用于返回Computer的详细信息
    (2)编写PC子类,继承Computer类,添加特有属性【品牌brand】
    (3)编写NotePad子类,继承Computer类,添加特有属性【color】//同学们自己写。
    (4)编写Test类,在main方法中创建PC和NotePad对象,分别给对象中特有的属性赋值,以及从Computer类继承的属性赋值,并使用方法并打印输出信息
package com.hspedu.extend_.exercise;

//编写Computer类,包含CPU、内存、硬盘等属性,getDetails方法用于返回Computer的详细信息
public class Computer {
    
    
    private String cpu;
    private int memory;
    private int disk;
    public Computer(String cpu, int memory, int disk) {
    
    
        this.cpu = cpu;
        this.memory = memory;
        this.disk = disk;
    }
    //返回Computer信息
    public String getDetails() {
    
    
        return "cpu=" + cpu + " memory=" + memory + " disk=" + disk;
    }

    public String getCpu() {
    
    
        return cpu;
    }

    public void setCpu(String cpu) {
    
    
        this.cpu = cpu;
    }

    public int getMemory() {
    
    
        return memory;
    }

    public void setMemory(int memory) {
    
    
        this.memory = memory;
    }

    public int getDisk() {
    
    
        return disk;
    }

    public void setDisk(int disk) {
    
    
        this.disk = disk;
    }
}

package com.hspedu.extend_.exercise;

//编写PC子类,继承Computer类,添加特有属性【品牌brand】

public class PC extends Computer{
    
    

    private String brand;
    //这里IDEA 根据继承的规则,自动把构造器的调用写好
    //这里也体现: 继承设计的基本思想,父类的构造器完成父类属性初始化
    //子类的构造器完成子类属性初始化
    public PC(String cpu, int memory, int disk, String brand) {
    
    
        super(cpu, memory, disk);
        this.brand = brand;
    }
    public String getBrand() {
    
    
        return brand;
    }
    public void setBrand(String brand) {
    
    
        this.brand = brand;
    }
    public void printInfo() {
    
    
        System.out.println("PC信息=");
//        System.out.println(getCpu() + getMemory() + getDisk());
        //调用父类的getDetails方法,得到相关属性信息..
        System.out.println(getDetails() + " brand=" + brand);
    }

}

package com.hspedu.extend_.exercise;

public class ExtendsExercise03 {
    
    
    public static void main(String[] args) {
    
    
        PC pc = new PC("intel", 16, 500, "IBM");
        pc.printInfo();
    }
}
/*
编写Computer类,包含CPU、内存、硬盘等属性,getDetails方法用于返回Computer的详细信息
编写PC子类,继承Computer类,添加特有属性【品牌brand】
编写NotePad子类,继承Computer类,添加特有属性【color】//同学们自己写。
编写Test类,在main方法中创建PC和NotePad对象,分别给对象中特有的属性赋值,
以及从Computer类继承的属性赋值,并使用方法并打印输出信息
 */

9 super 关键字

9.1 基本介绍

super 代表父类的引用,用于访问父类的属性、方法、构造器

9.2 基本语法

(1)访问父类的属性,但不能访问父类的private属性

	super.属性名;

(2)访问父类的方法,不能访问父类的private方法

	super.方法名(参数列表);

(3)访问父类的构造器

	super(参数列表);//只能放在构造器的第一句,只能出现一句!
package com.hspedu.super_;

public class A extends Base{
    
    
    //4个属性
    //public int n1 = 100;
    protected int n2 = 200;
    int n3 = 300;
    private int n4 = 400;

    public A() {
    
    }
    public A(String name) {
    
    }
    public A(String name, int age) {
    
    }

//    public void cal() {
    
    
//        System.out.println("A类的cal() 方法...");
//    }

    public void test100() {
    
    
    }

    protected void test200() {
    
    
    }

    void test300() {
    
    
    }

    private void test400() {
    
    
    }
}


package com.hspedu.super_;

public class B extends A {
    
    

    public int n1 = 888;

    //编写测试方法
    public void test() {
    
    
        //super的访问不限于直接父类,如果爷爷类和本类中有同名的成员,也可以使用super去访问爷爷类的成员;
        // 如果多个基类(上级类)中都有同名的成员,使用super访问遵循就近原则。A->B->C

        System.out.println("super.n1=" + super.n1);
        super.cal();
    }

    //访问父类的属性 , 但不能访问父类的private属性 [案例]super.属性名
    public void hi() {
    
    
        System.out.println(super.n1 + " " + super.n2 + " " + super.n3 );
    }
    public void cal() {
    
    
        System.out.println("B类的cal() 方法...");
    }
    public void sum() {
    
    
        System.out.println("B类的sum()");
        //希望调用父类-A 的cal方法
        //这时,因为子类B没有cal方法,因此我可以使用下面三种方式

        //找cal方法时(cal() 和 this.cal()),顺序是:
        // (1)先找本类,如果有,则调用
        // (2)如果没有,则找父类(如果有,并可以调用,则调用)
        // (3)如果父类没有,则继续找父类的父类,整个规则,就是一样的,直到 Object类
        // 提示:如果查找方法的过程中,找到了,但是不能访问, 则报错, cannot access
        //      如果查找方法的过程中,没有找到,则提示方法不存在
        //cal();
        this.cal(); //等价 cal

        //找cal方法(super.call()) 的顺序是直接查找父类,其他的规则一样
        //super.cal();

        //演示访问属性的规则
        //n1 和 this.n1 查找的规则是
        //(1) 先找本类,如果有,则调用
        //(2) 如果没有,则找父类(如果有,并可以调用,则调用)
        //(3) 如果父类没有,则继续找父类的父类,整个规则,就是一样的,直到 Object类
        // 提示:如果查找属性的过程中,找到了,但是不能访问, 则报错, cannot access
        //      如果查找属性的过程中,没有找到,则提示属性不存在
        System.out.println(n1);
        System.out.println(this.n1);

        //找n1 (super.n1) 的顺序是直接查找父类属性,其他的规则一样
        System.out.println(super.n1);

    }
    //访问父类的方法,不能访问父类的private方法 super.方法名(参数列表);
    public void ok() {
    
    
        super.test100();
        super.test200();
        super.test300();
        //super.test400();//不能访问父类private方法
    }
    //访问父类的构造器(这点前面用过):super(参数列表);只能放在构造器的第一句,只能出现一句!
    public  B() {
    
    
        //super();
        //super("jack", 10);
        super("jack");
    }
}

package com.hspedu.super_;

public class Super01 {
    
    
    public static void main(String[] args) {
    
    
        B b = new B();//子类对象
        //b.sum();
        b.test();
    }
}


package com.hspedu.super_;

public class Base {
    
     //父类是Object

    public int n1 = 999;
    public int age = 111;
    public void cal() {
    
    
        System.out.println("Base类的cal() 方法...");
    }
    public void eat() {
    
    
        System.out.println("Base类的eat().....");
    }
}

9.3 super 给编程带来的便利/细节

(1)调用父类的构造器的好处(分工明确,父类属性由父类初始化,子类的属性由子类初始化)
(2)当子类中有和父类中的成员(属性和方法)重名时,为了访问父类的成员,必须通过super。如果没有重名,使用super、this、直接访问是一样的效果!
(3)super的访问不限于直接父类,如果爷爷类和本类中有同名的成员,也可以使用super去访问爷爷类的成员;如果多个基类(上级类)中都有同名的成员,使用super访问遵循就近原则。A–>B–>C,当然也需要遵循访问权限的相关规则。

9.4 super 和 this 的比较

在这里插入图片描述

10 方法重写/覆盖(override)

10.1 基本介绍

简单地说:方法覆盖(重写)就是子类有一个方法,和父类的某个方法和名称、返回类型、参数一样,那么我们就说子类的这个方法覆盖了父类的方法。

package com.hspedu.override_;

public class Animal {
    
    
    public void cry() {
    
    
        System.out.println("动物叫唤..");
    }

    public Object m1() {
    
    
        return null;
    }

    public String m2() {
    
    
        return null;
    }

    public AAA m3() {
    
    
        return null;
    }
    protected void eat() {
    
    

    }
}

package com.hspedu.override_;

public class Dog extends Animal{
    
    
    //解读
    //1. 因为Dog 是 Animal子类
    //2. Dog的 cry方法和 Animal的 cry定义形式一样(名称、返回类型、参数)
    //3. 这时我们就说 Dog的cry方法,重写了Animal的cry方法
    public void cry() {
    
    
        System.out.println("小狗汪汪叫..");
    }

    //细节: 子类方法的返回类型和父类方法返回类型一样,
    //      或者是父类返回类型的子类 比如 父类 返回类型是 Object ,
    //      子类方法返回类型是String
    public String m1() {
    
    
        return null;
    }
    //这里Object 不是 String的子类,因此编译错误
//    public Object m2() {
    
    
//        return null;
//    }

//    public BBB m3() {
    
    
//        return null;
//    }
    //细节: 子类方法不能缩小父类方法的访问权限 【演示】
    //public > protected > 默认>private
    public void eat() {
    
    

    }
}

class AAA {
    
    

}

class BBB extends AAA  {
    
    

}

package com.hspedu.override_;

public class Override01 {
    
    
    public static void main(String[] args) {
    
    
        //演示方法重写的情况
        Dog dog = new Dog();
        dog.cry();//ctrl+b
    }
}


10.3 注意事项和使用细节

方法重写也叫方法覆盖,需要满足下面的条件
(1)子类的方法的形参列表方法名称,要和父类方法的形参列表方法名称完全一致。
(2)子类方法的返回类型和父类方法返回类型一样,或者是父类返回类型的子类,比如 父类的返回类型是 Object,子类方法返回类型是String
(3)子类方法不能缩小父类方法的访问权限
public > protected > 默认 > private

10.4 方法的重写和重载比较

在这里插入图片描述

11 面向对象编程-多态

11.1 先看一个问题

在这里插入图片描述

11.2 多[多种]态[状态]基本介绍

方法或对象具有多种形态。是面向对象的第三大特征,多态是建立在封装和继承基础之上的。

11.3 多态的具体体现

  1. 方法的多态 PloyMethod.java
    重写和重载就体现多态
package com.hspedu.poly_;

public class PloyMethod {
    
    
    public static void main(String[] args) {
    
    
        //方法重载体现多态
        A a = new A();
        //这里我们传入不同的参数,就会调用不同sum方法,就体现多态
        System.out.println(a.sum(10, 20));
        System.out.println(a.sum(10, 20, 30));

        //方法重写体现多态
        B b = new B();
        a.say();
        b.say();

    }
}
class B {
    
     //父类
    public void say() {
    
    
        System.out.println("B say() 方法被调用...");
    }
}
class A extends B {
    
    //子类
    public int sum(int n1, int n2){
    
    //和下面sum 构成重载
        return n1 + n2;
    }
    public int sum(int n1, int n2, int n3){
    
    
        return n1 + n2 + n3;
    }


    public void say() {
    
    
        System.out.println("A say() 方法被调用...");
    }
}

  1. 对象的多态 (核心,困难,重点)
    (1)一个对象的编译类型和运行类型可以不一致
    (2)编译类型在定义对象时,就确定了,不能改变
    (3)运行类型时可以变化的
    (4)编译类型看定义时 = 号 的左边,运行类型看 = 号的 右边
package com.hspedu.poly_.objectpoly_;

public class Animal {
    
    
    public void  cry() {
    
    
        System.out.println("Animal cry() 动物在叫....");
    }
}

package com.hspedu.poly_.objectpoly_;

public class Cat extends Animal {
    
    

    public void cry() {
    
    
        System.out.println("Cat cry() 小猫喵喵叫...");
    }
}

package com.hspedu.poly_.objectpoly_;

public class Dog extends Animal {
    
    

    public void cry() {
    
    
        System.out.println("Dog cry() 小狗汪汪叫...");
    }
}

package com.hspedu.poly_.objectpoly_;

public class PolyObject {
    
    
    public static void main(String[] args) {
    
    
        //体验对象多态特点
        //animal 编译类型就是 Animal , 运行类型 Dog
        Animal animal = new Dog();
        //因为运行时 , 执行到改行时,animal运行类型是Dog,所以cry就是Dog的cry
        animal.cry(); //小狗汪汪叫

        //animal 编译类型 Animal,运行类型就是 Cat
        animal = new Cat();
        animal.cry(); //小猫喵喵叫
    }
}

11.4 多态注意事项和细节讨论

11.4.1 多态的前提是:两个对象(类)存在继承关系

11.4.2 多态的向上转型

在这里插入图片描述

11.4.3 多态向下转型

在这里插入图片描述

package com.hspedu.poly_.detail_;

public class Animal {
    
    
    String name = "动物";
    int age = 10;
    public void sleep(){
    
    
        System.out.println("睡");
    }
    public void run(){
    
    
        System.out.println("跑");
    }
    public void eat(){
    
    
        System.out.println("吃");
    }
    public void show(){
    
    
        System.out.println("hello,你好");
    }

}

package com.hspedu.poly_.detail_;

public class Cat extends Animal {
    
    
    public void eat(){
    
    //方法重写
        System.out.println("猫吃鱼");
    }
    public void catchMouse(){
    
    //Cat特有方法
        System.out.println("猫抓老鼠");
    }
}

package com.hspedu.poly_.detail_;

public class Dog extends Animal {
    
    //Dog是Animal的子类
}

package com.hspedu.poly_.detail_;

public class PolyDetail {
    
    
    public static void main(String[] args) {
    
    

        //向上转型: 父类的引用指向了子类的对象
        //语法:父类类型引用名 = new 子类类型();
        Animal animal = new Cat();
        Object obj = new Cat();//可以吗? 可以 Object 也是 Cat的父类

        //向上转型调用方法的规则如下:
        //(1)可以调用父类中的所有成员(需遵守访问权限)
        //(2)但是不能调用子类的特有的成员
        //(3)因为在编译阶段,能调用哪些成员,是由编译类型来决定的
        //animal.catchMouse();错误
        //(4)最终运行效果看子类(运行类型)的具体实现, 即调用方法时,按照从子类(运行类型)开始查找方法
        //,然后调用,规则我前面我们讲的方法调用规则一致。
        animal.eat();//猫吃鱼..
        animal.run();//跑
        animal.show();//hello,你好
        animal.sleep();//睡

        //我们希望,可以调用Cat的 catchMouse方法
        //多态的向下转型
        //(1)语法:子类类型 引用名 =(子类类型)父类引用;
        //问一个问题? cat 的编译类型 Cat,运行类型是 Cat
        Cat cat = (Cat) animal;
        cat.catchMouse();//猫抓老鼠
        //(2)要求父类的引用必须指向的是当前目标类型的对象
        Dog dog = (Dog) animal; //可以吗?

        System.out.println("ok~~");
    }
}

11.4.4 属性没有重写之说!

属性的值看编译类型 【PolyDetail02.java】

package com.hspedu.poly_.detail_;

public class PolyDetail02 {
    
    
    public static void main(String[] args) {
    
    
        //属性没有重写之说!属性的值看编译类型
        Base base = new Sub();//向上转型
        System.out.println(base.count);// ? 看编译类型 10
        Sub sub = new Sub();
        System.out.println(sub.count);//?  20
    }
}

class Base {
    
     //父类
    int count = 10;//属性
}
class Sub extends Base {
    
    //子类
    int count = 20;//属性
}

11.4.5 instanceOf 比较操作符

用于判断对象的运行类型是否为 XX 类型或 XX 类型的子类型【举例说明】PolyDetail03.java

package com.hspedu.poly_.detail_;

public class PolyDetail03 {
    
    
    public static void main(String[] args) {
    
    
        BB bb = new BB();
        System.out.println(bb instanceof  BB);// true
        System.out.println(bb instanceof  AA);// true

        //aa 编译类型 AA, 运行类型是BB
        //BB是AA子类
        AA aa = new BB();
        System.out.println(aa instanceof AA);
        System.out.println(aa instanceof BB);

        Object obj = new Object();
        System.out.println(obj instanceof AA);//false
        String str = "hello";
        //System.out.println(str instanceof AA);
        System.out.println(str instanceof Object);//true
    }
}

class AA {
    
    } //父类
class BB extends AA {
    
    }//子类

11.5 课堂练习

(1)请说出下面的每条语言,哪些是正确的,哪些是错误的,为什么?
在这里插入图片描述(2)

package com.hspedu.poly_;

public class PolyExercise02 {
    
    
    public static void main(String[] args) {
    
    
        Sub s = new Sub();
        System.out.println(s.count);//20
        s.display();//20
        Base b = s;
        System.out.println(b == s);//T
        System.out.println(b.count);//10
        b.display();//20
    }

}

class Base {
    
    //父类
    int count = 10;

    public void display() {
    
    
        System.out.println(this.count);
    }
}

class Sub extends Base {
    
    //子类
    int count = 20;

    public void display() {
    
    
        System.out.println(this.count);
    }
}


11.6 java 的动态绑定机制(非常非常重要.)

Java 重要特性: 动态绑定机制
在这里插入图片描述

package com.hspedu.poly_.dynamic_;

public class DynamicBinding {
    
    
    public static void main(String[] args) {
    
    
        //a 的编译类型 A, 运行类型 B
        A a = new B();//向上转型
        System.out.println(a.sum());//?40 -> 30
        System.out.println(a.sum1());//?30-> 20
    }
}

class A {
    
    //父类
    public int i = 10;
    //动态绑定机制:

    public int sum() {
    
    //父类sum()
        return getI() + 10;//20 + 10
    }

    public int sum1() {
    
    //父类sum1()
        return i + 10;//10 + 10
    }

    public int getI() {
    
    //父类getI
        return i;
    }
}

class B extends A {
    
    //子类
    public int i = 20;

//    public int sum() {
    
    
//        return i + 20;
//    }

    public int getI() {
    
    //子类getI()
        return i;
    }

//    public int sum1() {
    
    
//        return i + 10;
//    }
}

11.8 多态的应用

11.8.1 多态数组

com.hspedu.poly_.polyarr_ 包 PloyArray.java
数组的定义类型为父类类型,里面保存的实际元素类型为子类类型
应用实例:现有一个继承结构如下:要求创建 1 个 Person 对象、2 个 Student 对象和 2 个 Teacher 对象, 统一放在数组
中,并调用每个对象say 方法.
应用实例升级:如何调用子类特有的方法,比如Teacher 有一个 teach , Student 有一个 study 怎么调用?

package com.hspedu.poly_.polyarr_;

public class Person {
    
    //父类
    private String name;
    private int age;

    public Person(String name, int age) {
    
    
        this.name = name;
        this.age = age;
    }

    public String getName() {
    
    
        return name;
    }

    public void setName(String name) {
    
    
        this.name = name;
    }

    public int getAge() {
    
    
        return age;
    }

    public void setAge(int age) {
    
    
        this.age = age;
    }

    public String say() {
    
    //返回名字和年龄
        return name + "\t" + age;
    }
}

package com.hspedu.poly_.polyarr_;

public class Student extends Person {
    
    
    private double score;

    public Student(String name, int age, double score) {
    
    
        super(name, age);
        this.score = score;
    }

    public double getScore() {
    
    
        return score;
    }

    public void setScore(double score) {
    
    
        this.score = score;
    }
    //重写父类say

    @Override
    public String say() {
    
    
        return "学生 " + super.say() + " score=" + score;
    }
    //特有的方法
    public void study() {
    
    
        System.out.println("学生 " + getName() + " 正在学java...");
    }
}

package com.hspedu.poly_.polyarr_;

public class Teacher extends Person {
    
    
    private double salary;

    public Teacher(String name, int age, double salary) {
    
    
        super(name, age);
        this.salary = salary;
    }

    public double getSalary() {
    
    
        return salary;
    }

    public void setSalary(double salary) {
    
    
        this.salary = salary;
    }
    //写重写父类的say方法

    @Override
    public String say() {
    
    
        return "老师 " + super.say() + " salary=" + salary;
    }
    //特有方法
    public void teach() {
    
    
        System.out.println("老师 " + getName() + " 正在讲java课程...");
    }
}

package com.hspedu.poly_.polyarr_;

public class PloyArray {
    
    
    public static void main(String[] args) {
    
    
        //应用实例:现有一个继承结构如下:要求创建1个Person对象、
        // 2个Student 对象和2个Teacher对象, 统一放在数组中,并调用每个对象say方法

        Person[] persons = new Person[5];
        persons[0] = new Person("jack", 20);
        persons[1] = new Student("mary", 18, 100);
        persons[2] = new Student("smith", 19, 30.1);
        persons[3] = new Teacher("scott", 30, 20000);
        persons[4] = new Teacher("king", 50, 25000);

        //循环遍历多态数组,调用say
        for (int i = 0; i < persons.length; i++) {
    
    
            //老师提示: person[i] 编译类型是 Person ,运行类型是是根据实际情况有JVM来判断
            System.out.println(persons[i].say());//动态绑定机制
            //这里大家聪明. 使用 类型判断 + 向下转型.
            if(persons[i]  instanceof  Student) {
    
    //判断person[i] 的运行类型是不是Student
                Student student = (Student)persons[i];//向下转型
                student.study();
                //小伙伴也可以使用一条语句 ((Student)persons[i]).study();
            } else if(persons[i] instanceof  Teacher) {
    
    
                Teacher teacher = (Teacher)persons[i];
                teacher.teach();
            } else if(persons[i] instanceof  Person){
    
    
                //System.out.println("你的类型有误, 请自己检查...");
            } else {
    
    
                System.out.println("你的类型有误, 请自己检查...");
            }

        }

    }
}

11.8.2 多态参数

在这里插入图片描述

package com.hspedu.poly_.polyparameter_;

public class Employee {
    
    
    private String name;
    private double salary;

    public Employee(String name, double salary) {
    
    
        this.name = name;
        this.salary = salary;
    }
    //得到年工资的方法
    public double getAnnual() {
    
    
        return 12 * salary;
    }

    public String getName() {
    
    
        return name;
    }

    public void setName(String name) {
    
    
        this.name = name;
    }

    public double getSalary() {
    
    
        return salary;
    }

    public void setSalary(double salary) {
    
    
        this.salary = salary;
    }
}

package com.hspedu.poly_.polyparameter_;

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 setBonus(double bonus) {
    
    
        this.bonus = bonus;
    }
    public void manage() {
    
    
        System.out.println("经理 " + getName() + " is managing");
    }
    //重写获取年薪方法
    @Override
    public double getAnnual() {
    
    
        return super.getAnnual() + bonus;
    }
}

package com.hspedu.poly_.polyparameter_;

public class Worker extends Employee {
    
    
    public Worker(String name, double salary) {
    
    
        super(name, salary);
    }
    public void work() {
    
    
        System.out.println("普通员工 " + getName() + " is working");
    }

    @Override
    public double getAnnual() {
    
     //因为普通员工没有其它收入,则直接调用父类方法
        return super.getAnnual();
    }
}

package com.hspedu.poly_.polyparameter_;

public class PloyParameter {
    
    
    public static void main(String[] args) {
    
    
        Worker tom = new Worker("tom", 2500);
        Manager milan = new Manager("milan", 5000, 200000);
        PloyParameter ployParameter = new PloyParameter();
        ployParameter.showEmpAnnual(tom);
        ployParameter.showEmpAnnual(milan);

        ployParameter.testWork(tom);
        ployParameter.testWork(milan);

    }

    //showEmpAnnual(Employee e)
    //实现获取任何员工对象的年工资,并在main方法中调用该方法 [e.getAnnual()]
    public void showEmpAnnual(Employee e) {
    
    
        System.out.println(e.getAnnual());//动态绑定机制.
    }
    //添加一个方法,testWork,如果是普通员工,则调用work方法,如果是经理,则调用manage方法
    public void testWork(Employee e) {
    
    
        if(e instanceof  Worker) {
    
    
            ((Worker) e).work();//有向下转型操作
        } else if(e instanceof Manager) {
    
    
            ((Manager) e).manage();//有向下转型操作
        } else {
    
    
            System.out.println("不做处理...");
        }
    }
}

12 Object 类详解

12.1 equals 方法

12.1.1 ==和 equals 的对比 [面试题]

在这里插入图片描述

package com.hspedu.object_;

public class Equals01 {
    
    

    public static void main(String[] args) {
    
    
        A a = new A();
        A b = a;
        A c = b;
        System.out.println(a == c);//true
        System.out.println(b == c);//true
        B bObj = a;
        System.out.println(bObj == c);//true
        int num1 = 10;
        double num2 = 10.0;
        System.out.println(num1 == num2);//基本数据类型,判断值是否相等

        //equals 方法,源码怎么查看.
        //把光标放在equals方法,直接输入ctrl+b
        //如果你使用不了. 自己配置. 即可使用.

        /*
        //带大家看看Jdk的源码 String类的 equals方法
        //把Object的equals方法重写了,变成了比较两个字符串值是否相同
        public boolean equals(Object anObject) {
        if (this == anObject) {//如果是同一个对象
            return true;//返回true
        }
        if (anObject instanceof String) {//判断类型
            String anotherString = (String)anObject;//向下转型
            int n = value.length;
            if (n == anotherString.value.length) {//如果长度相同
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {//然后一个一个的比较字符
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;//如果两个字符串的所有字符都相等,则返回true
            }
        }
        return false;//如果比较的不是字符串,则直接返回false
    }
         */


        "hello".equals("abc");

        //看看Object类的 equals 是
        /*
        //即Object 的equals 方法默认就是比较对象地址是否相同
        //也就是判断两个对象是不是同一个对象.
         public boolean equals(Object obj) {
            return (this == obj);
        }
         */


        /*
        //从源码可以看到 Integer 也重写了Object的equals方法,
        //变成了判断两个值是否相同
        public boolean equals(Object obj) {
            if (obj instanceof Integer) {
                return value == ((Integer)obj).intValue();
            }
            return false;
        }
         */
        Integer integer1 = new Integer(1000);
        Integer integer2 = new Integer(1000);
        System.out.println(integer1 == integer2);//false
        System.out.println(integer1.equals(integer2));//true

        String str1 = new String("hspedu");
        String str2 = new String("hspedu");
        System.out.println(str1 == str2);//false
        System.out.println(str1.equals(str2));//true




    }
}

class B {
    
    }
class A extends B {
    
    }

12.2 如何重写 equals 方法

应用实例: 判断两个 Person 对象的内容是否相等,如果两个 Person 对象的各个属性值都一样,则返回 true,反之 false。

package com.hspedu.object_;

public class EqualsExercise01 {
    
    
    public static void main(String[] args) {
    
    
        Person person1 = new Person("jack", 10, '男');
        Person person2 = new Person("jack", 20, '男');

        System.out.println(person1.equals(person2));//假
    }
}
//判断两个Person对象的内容是否相等,
//如果两个Person对象的各个属性值都一样,则返回true,反之false
class Person{
    
     //extends Object
    private String name;
    private int age;
    private char gender;

    //重写Object 的 equals方法
    public boolean equals(Object obj) {
    
    
        //判断如果比较的两个对象是同一个对象,则直接返回true
        if(this == obj) {
    
    
            return true;
        }
        //类型判断
        if(obj instanceof  Person) {
    
    //是Person,我们才比较

            //进行 向下转型, 因为我需要得到obj的 各个属性
            Person p = (Person)obj;
            return this.name.equals(p.name) && this.age == p.age && this.gender == p.gender;
        }
        //如果不是Person ,则直接返回false
        return false;

    }

    public Person(String name, int age, char gender) {
    
    
        this.name = name;
        this.age = age;
        this.gender = gender;
    }

    public String getName() {
    
    
        return name;
    }

    public void setName(String name) {
    
    
        this.name = name;
    }

    public int getAge() {
    
    
        return age;
    }

    public void setAge(int age) {
    
    
        this.age = age;
    }

    public char getGender() {
    
    
        return gender;
    }

    public void setGender(char gender) {
    
    
        this.gender = gender;
    }

}

12.3 练习题

package com.hspedu.object_;

public class EqualsExercise02 {
    
    
    public static void main(String[] args) {
    
    

        Person_ p1 = new Person_();
        p1.name = "hspedu";

        Person_ p2 = new Person_();
        p2.name = "hspedu";

        System.out.println(p1==p2); //False
        System.out.println(p1.name .equals( p2.name));//T
        System.out.println(p1.equals(p2));//False

        String s1 = new String("asdf");

        String s2 = new String("asdf");
        System.out.println(s1.equals(s2));//T
        System.out.println(s1==s2); //F

    }
}

class Person_{
    
    //类
    public String name;
}

//代码如下 EqualsExercise03.java 2min
int it = 65;
float fl = 65.0f;
System.out.println(6565.0f 是否相等?” + (it == fl));//T
char ch1 =A; char ch2 = 12;
System.out.println(65 和‘A’是否相等?” + (it == ch1));//T
System.out.println(12 和 ch2 是否相等?” + (12 == ch2));//T
String str1 = new String("hello");
String str2 = new String("hello");
System.out.println("str1 和 str2 是否相等?"+ (str1 == str2)); //F
System.out.println(“str1 是否 equals str2?”+(str1.equals(str2)));//T
System.out.println(“hello” == new java.sql.Date()); //编译错误

12.4 hashCode 方法

在这里插入图片描述

  1. 提高具有哈希结构的容器的效率!
  2. 两个引用,如果指向的是同一个对象,则哈希值肯定是一样的!
  3. 两个引用,如果指向的是不同对象,则哈希值是不一样的
  4. 哈希值主要根据地址号来的!, 不能完全将哈希值等价于地址。
  5. 案例演示[HashCode_.java]: obj.hashCode() [测试:A obj1 = new A(); A obj2 = new A(); A obj3 = obj1]
  6. 后面在集合,中 hashCode 如果需要的话,也会重写
package com.hspedu.object_;

public class HashCode_ {
    
    
    public static void main(String[] args) {
    
    

        AA aa = new AA();
        AA aa2 = new AA();
        AA aa3 = aa;
        System.out.println("aa.hashCode()=" + aa.hashCode());
        System.out.println("aa2.hashCode()=" + aa2.hashCode());
        System.out.println("aa3.hashCode()=" + aa3.hashCode());


    }
}
class AA {
    
    }

12.5 toString 方法

  1. 基本介绍
    默认返回:全类名+@+哈希值的十六进制,【查看 Object 的 toString 方法】
    子类往往重写 toString 方法,用于返回对象的属性信息
  2. 重写 toString 方法,打印对象或拼接对象时,都会自动调用该对象的 toString 形式.
  3. 当直接输出一个对象时,toString 方法会被默认的调用, 比如 System.out.println(monster); 就会默认调用 monster.toString()
package com.hspedu.object_;

public class ToString_ {
    
    
    public static void main(String[] args) {
    
    

        /*
        Object的toString() 源码
        (1)getClass().getName() 类的全类名(包名+类名 )
        (2)Integer.toHexString(hashCode()) 将对象的hashCode值转成16进制字符串
        public String toString() {
            return getClass().getName() + "@" + Integer.toHexString(hashCode());
        }
         */

        Monster monster = new Monster("小妖怪", "巡山的", 1000);
        System.out.println(monster.toString() + " hashcode=" + monster.hashCode());

        System.out.println("==当直接输出一个对象时,toString 方法会被默认的调用==");
        System.out.println(monster); //等价 monster.toString()



    }
}

class Monster {
    
    
    private String name;
    private String job;
    private double sal;

    public Monster(String name, String job, double sal) {
    
    
        this.name = name;
        this.job = job;
        this.sal = sal;
    }

    //重写toString方法, 输出对象的属性
    //使用快捷键即可 alt+insert -> toString
    @Override
    public String toString() {
    
     //重写后,一般是把对象的属性值输出,当然程序员也可以自己定制
        return "Monster{" +
                "name='" + name + '\'' +
                ", job='" + job + '\'' +
                ", sal=" + sal +
                '}';
    }

    @Override
    protected void finalize() throws Throwable {
    
    
        System.out.println("fin..");
    }
}

12.6 finalize 方法

  1. 当对象被回收时,系统自动调用该对象的 finalize 方法。子类可以重写该方法,做一些释放资源的操作【演示】
  2. 什么时候被回收:当某个对象没有任何引用时,则 jvm 就认为这个对象是一个垃圾对象,就会使用垃圾回收机制来
    销毁该对象,在销毁该对象前,会先调用 finalize 方法。
  3. 垃圾回收机制的调用,是由系统来决定(即有自己的 GC 算法), 也可以通过 System.gc() 主动触发垃圾回收机制

13 断点调试(debug)

13.1 一个实际需求

在这里插入图片描述

13.2 断点调试介绍

在这里插入图片描述

13.3 断点调试的快捷键

F7(跳入) F8(跳过) shift+F8(跳出) F9(resume,执行到下一个断点)
F7:跳入方法内
F8: 逐行执行代码. shift+F8: 跳出方法
在这里插入图片描述

14 本章作业

14.1 冒泡排序

定义一个Person类 {name, age, job}, 初始化Person 对象数组,有3个person对象,并按照 age 从 大到 小进行排序, 提示,使用冒泡排序

package com.hspedu.homework;

public class Homework01 {
    
    

    public static void main(String[] args) {
    
    

        //初始化Person 对象数组,有3个person对象
        Person[] persons = new Person[3];
        persons[0] = new Person("mary",30, "PHP工程师");
        persons[1] = new Person("tom",50, "大数据工程师");
        persons[2] = new Person("smith",10, "JavaEE工程师");



        //输出当前对象数组
        for (int i = 0; i < persons.length; i++) {
    
    
            System.out.println(persons[i]);//默认对象的.toString()
        }

        //使用冒泡排序
        Person tmp = null;//临时变量,用于交换
        for(int i = 0; i < persons.length -1 ;i++) {
    
    //外层循环
            for(int j = 0; j < persons.length -1 - i; j++) {
    
    //内层循环
                //并按照 age 从 大到 小进行排序, 如果前面的人的age < 后面人的年龄,就交换
                //要求按照名字的长度从小到大 if(persons[i].getName().length() > persons[i+1].getName().length())
                if(persons[j].getAge() > persons[j+1].getAge()) {
    
    
                    tmp = persons[j];
                    persons[j] = persons[j+1];
                    persons[j+1]= tmp;
                }

            }
        }

        System.out.println("排序后的效果");
        for (int i = 0; i < persons.length; i++) {
    
    
            System.out.println(persons[i]);//默认对象的.toString()
        }

    }

    /*
    定义一个Person类 {name, age, job}, 初始化Person 对象数组,有3个person对象,
    并按照 age 从 大到 小进行排序, 提示,使用冒泡排序
     */
}

class Person {
    
    
    private String name;
    private int age;
    private String job;

    public Person(String name, int age, String job) {
    
    
        this.name = name;
        this.age = age;
        this.job = job;
    }

    public String getName() {
    
    
        return name;
    }

    public void setName(String name) {
    
    
        this.name = name;
    }

    public int getAge() {
    
    
        return age;
    }

    public void setAge(int age) {
    
    
        this.age = age;
    }

    public String getJob() {
    
    
        return job;
    }

    public void setJob(String job) {
    
    
        this.job = job;
    }

    @Override
    public String toString() {
    
    
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", job='" + job + '\'' +
                '}';
    }
}


14.2 写出四种访问修饰符各自访问权限

在这里插入图片描述

14.3 编写老师类

(1) 要求有属性“姓名name”,“年龄age”,“职称post”,“基本工资salary”
(2) 编写业务方法, introduce(),实现输出一个教师的信息。

package com.hspedu.homework;


/*
(1) 要求有属性“姓名name”,“年龄age”,“职称post”,“基本工资salary”
(2) 编写业务方法, introduce(),实现输出一个教师的信息。

 */
public class Teacher {
    
    
    private String name;
    private int age;
    private String post;
    private double salary;
    //这里我们在增加一个工资级别
    private double grade;

    public Teacher(String name, int age, String post, double salary, double grade) {
    
    
        this.name = name;
        this.age = age;
        this.post = post;
        this.salary = salary;
        this.grade = grade;
    }

    public String getName() {
    
    
        return name;
    }

    public void setName(String name) {
    
    
        this.name = name;
    }

    public int getAge() {
    
    
        return age;
    }

    public void setAge(int age) {
    
    
        this.age = age;
    }

    public String getPost() {
    
    
        return post;
    }

    public void setPost(String post) {
    
    
        this.post = post;
    }

    public double getSalary() {
    
    
        return salary;
    }

    public void setSalary(double salary) {
    
    
        this.salary = salary;
    }

    public double getGrade() {
    
    
        return grade;
    }

    public void setGrade(double grade) {
    
    
        this.grade = grade;
    }
    public void introduce() {
    
    
        System.out.println("name: " + name + " age: " + age
                + " post: " + post + " salary:" + salary + " grade:" + grade);
    }
}

package com.hspedu.homework;

//子类
public class Professor extends Teacher {
    
    

    //特有属性...
    public Professor(String name, int age, String post, double salary, double grade) {
    
    
        super(name, age, post, salary, grade);
    }

    @Override
    public void introduce() {
    
    
        System.out.println(" 这是教授的信息 ");
        super.introduce();
    }
}

package com.hspedu.homework;

public class Homework03 {
    
    
    public static void main(String[] args) {
    
    
        Professor professor = new Professor("贾宝玉", 30, "高级职称", 30000, 1.3);
        professor.introduce();
    }
}


14.4

在这里插入图片描述

package com.hspedu.homework;

import java.sql.SQLOutput;

public class Employee {
    
    

    //属性
    //员工属性:姓名,单日工资,工作天数
    private String name;
    private double daySal;
    private int workDays;
    //分析出还有一个属性等级
    private double grade;

    //方法[构造器,getter 和 setter]
    //打印工资方法
    //方法 void printSal() {}
    public void printSal() {
    
    
        System.out.println(name + " 工资=" + daySal * workDays * grade);
    }

    public Employee(String name, double daySal, int workDays, double grade) {
    
    
        this.name = name;
        this.daySal = daySal;
        this.workDays = workDays;
        this.grade = grade;
    }

    public String getName() {
    
    
        return name;
    }

    public void setName(String name) {
    
    
        this.name = name;
    }

    public double getDaySal() {
    
    
        return daySal;
    }

    public void setDaySal(double daySal) {
    
    
        this.daySal = daySal;
    }

    public int getWorkDays() {
    
    
        return workDays;
    }

    public void setWorkDays(int workDays) {
    
    
        this.workDays = workDays;
    }

    public double getGrade() {
    
    
        return grade;
    }

    public void setGrade(double grade) {
    
    
        this.grade = grade;
    }
}

package com.hspedu.homework;

public class Manager extends Employee {
    
    
    //特有属性
    private double bonus;
    //创建Manager对象时,奖金是多少并不是确定的,因为老师在构造器中,不给bonus
    //,可以通过setBonus
    public Manager(String name, double daySal, int workDays, double grade) {
    
    
        super(name, daySal, workDays, grade);
    }

    //方法:重写父类的 printSal


    @Override
    public void printSal() {
    
    
        //因为经理的工资计算方式和Employee不一样,所以我们重写
        System.out.println("经理 " + getName() + " 工资是="
                + (bonus + getDaySal() * getWorkDays() * getGrade()));
    }

    public double getBonus() {
    
    
        return bonus;
    }

    public void setBonus(double bonus) {
    
    
        this.bonus = bonus;
    }
}

package com.hspedu.homework;

public class Worker extends Employee{
    
    
    //分析普通员工没有特有的属性

    public Worker(String name, double daySal, int workDays, double grade) {
    
    
        super(name, daySal, workDays, grade);
    }

    //重写printSal
    //因为普通员工和Employee输出工资情况一下,所以直接调用父类的printSal()
    @Override
    public void printSal() {
    
    
        System.out.print("普通员工 ");//自己的输出信息
        super.printSal();//调用父类的方法,复用代码
    }
}

package com.hspedu.homework;

public class Homework04 {
    
    
    public static void main(String[] args) {
    
    
        Manager manage = new Manager("刘备", 100, 20, 1.2);
        //设置奖金
        manage.setBonus(3000);
        //打印经理的工资情况
        manage.printSal();

        Worker worker = new Worker("关羽",50, 10, 1.0);
        worker.printSal();

    }
}

14.5

在这里插入图片描述

package com.hspedu.homework.homework5;

public class Employee {
    
     //父类
    //属性
    //分析有一个带薪的月份 13 , 15, 12
    private String name;
    private double sal;
    private int salMonth = 12;
    //方法
    //打印全年工资
    public void printSal() {
    
    
        System.out.println(name + " 年工资是: " + (sal * salMonth));
    }

    public Employee(String name, double sal) {
    
    
        this.name = name;
        this.sal = sal;
    }

    public String getName() {
    
    
        return name;
    }

    public void setName(String name) {
    
    
        this.name = name;
    }

    public double getSal() {
    
    
        return sal;
    }

    public void setSal(double sal) {
    
    
        this.sal = sal;
    }

    public int getSalMonth() {
    
    
        return salMonth;
    }

    public void setSalMonth(int salMonth) {
    
    
        this.salMonth = salMonth;
    }
}

package com.hspedu.homework.homework5;

public class Worker extends Employee{
    
     //子类
    //属性
    //工人,农民,服务生只有基本工资 sal
    public Worker(String name, double sal) {
    
    
        super(name, sal);
    }

    //方法
    @Override
    public void printSal() {
    
    
        System.out.print("工人 ");
        super.printSal();//使用父类的printSal()
    }
}

package com.hspedu.homework.homework5;

public class Peasant extends Employee {
    
    //子类
    //属性
    //农民,服务生只有基本工资 sal

    //方法
    public Peasant(String name, double sal) {
    
    
        super(name, sal);
    }
    //年工资

    @Override
    public void printSal() {
    
    
        System.out.print("农民 ");
        super.printSal();
    }
}

package com.hspedu.homework.homework5;

public class Teacher extends Employee{
    
    //子类
    //特有属性
    private int classDays; //一年上课次数
    private double classSal; //课时费

    public Teacher(String name, double sal) {
    
    
        super(name, sal);
    }
    //方法-重写printSal

    @Override
    public void printSal() {
    
     //老师不能使用super.printSal()
        System.out.print("老师 ");
        System.out.println(getName() + " 年工资是: "
                + (getSal() * getSalMonth() + classDays * classSal ));
    }

    public int getClassDays() {
    
    
        return classDays;
    }

    public void setClassDays(int classDays) {
    
    
        this.classDays = classDays;
    }

    public double getClassSal() {
    
    
        return classSal;
    }

    public void setClassSal(double classSal) {
    
    
        this.classSal = classSal;
    }
}

package com.hspedu.homework.homework5;

public class Scientist extends Employee{
    
     //子类

    //特有属性
    //年终奖 bonus
    private double bonus;

    //方法
    public Scientist(String name, double sal) {
    
    
        super(name, sal);
    }
    //重写年工资打印

    @Override
    public void printSal() {
    
    
        System.out.print("科学家 ");
        System.out.println(getName() + " 年工资是: " + (getSal() * getSalMonth() + bonus));
    }

    public double getBonus() {
    
    
        return bonus;
    }

    public void setBonus(double bonus) {
    
    
        this.bonus = bonus;
    }
}

package com.hspedu.homework.homework5;

public class Homework05 {
    
    
    public static void main(String[] args) {
    
    
        Worker jack = new Worker("jack", 10000);
        jack.setSalMonth(15);//灵活额修改带薪月份
        jack.printSal();

        Peasant smith = new Peasant("smith", 20000);
        smith.printSal();

        //老师测试
        Teacher teacher = new Teacher("顺平", 2000);
        //老师有课时费
        teacher.setClassDays(360);
        teacher.setClassSal(1000);
        teacher.printSal();

        //科学家
        Scientist scientist = new Scientist("钟南山", 20000);
        scientist.setBonus(2000000);
        scientist.printSal();
    }
}

14.6 程序阅读题

在这里插入图片描述

14.7

在这里插入图片描述

14.8

在这里插入图片描述

package com.hspedu.homework;

public class BankAccount {
    
    //父类
    private double balance ;//余额
    public BankAccount(double initialBalance) {
    
    
        this.balance = initialBalance;
    }
    //存款
    public void deposit(double amount)  {
    
    
        balance += amount;
    }
    //取款
    public void withdraw(double amount)  {
    
    
        balance -= amount;
    }

    public double getBalance() {
    
    
        return balance;
    }

    public void setBalance(double balance) {
    
    
        this.balance = balance;
    }
}

package com.hspedu.homework;


/*
在上面类的基础上扩展 新类CheckingAccount对每次存款和取款都收取1美元的手续费
 */
public class CheckingAccount extends BankAccount{
    
    //新的账号
    //属性
    public CheckingAccount(double initialBalance) {
    
    
        super(initialBalance);
    }

    @Override
    public void deposit(double amount) {
    
    //存款
        super.deposit(amount - 1);//巧妙的使用了父类的 deposit
        //1 块钱转入银行的账号
    }

    @Override
    public void withdraw(double amount) {
    
    //取款
        super.withdraw(amount + 1);
        //1 块钱转入银行的账号
    }
}

package com.hspedu.homework;

/*
扩展前一个练习的BankAccount类,
新类SavingsAccount每个月都有利息产生(earnMonthlyInterest方法被调用),
并且有每月三次免手续费的存款或取款。在earnMonthlyInterest方法中重置交易计数
 */
public class SavingsAccount extends BankAccount {
    
    

    //分析
    //新增加属性
    private int count = 3;
    private double rate = 0.01;//利率

    public void earnMonthlyInterest() {
    
    //每个月初,我们统计上个月的利息,同时将count=3
        count = 3;//
        super.deposit(getBalance() * rate);
    }

    @Override
    public void deposit(double amount) {
    
    
        //判断是否还可以免手续费
        if(count > 0) {
    
    
            super.deposit(amount);
        } else {
    
    
            super.deposit(amount - 1);//1 块转入银行
        }
        count--;//减去一次
    }

    @Override
    public void withdraw(double amount) {
    
    //取款
        //判断是否还可以免手续费
        if(count > 0) {
    
    
            super.withdraw(amount);
        } else {
    
    
            super.withdraw(amount + 1);//1 块转入银行
        }
        count--;
    }

    public SavingsAccount(double initialBalance) {
    
    
        super(initialBalance);
    }


    public int getCount() {
    
    
        return count;
    }

    public void setCount(int count) {
    
    
        this.count = count;
    }

    public double getRate() {
    
    
        return rate;
    }

    public void setRate(double rate) {
    
    
        this.rate = rate;
    }
}

package com.hspedu.homework;

public class Homework08 {
    
    
    public static void main(String[] args) {
    
    
//        CheckingAccount checkingAccount = new CheckingAccount(1000);
//        checkingAccount.deposit(10);// 1010 - 1 = 1009
//        checkingAccount.withdraw(9);//1009 - 9 = 1000 -1= 999
//        System.out.println(checkingAccount.getBalance());

        //测试SavingsAccount
        SavingsAccount savingsAccount = new SavingsAccount(1000);
        savingsAccount.deposit(100);
        savingsAccount.deposit(100);
        savingsAccount.deposit(100);
        System.out.println(savingsAccount.getBalance());//1300
        savingsAccount.deposit(100);
        System.out.println(savingsAccount.getBalance());//1400-1=1399

        //月初,定时器自动调用一下 earnMonthlyInterest
        savingsAccount.earnMonthlyInterest();//统计利息
        System.out.println(savingsAccount.getBalance());//1399 + 13.99 =1412.99
        savingsAccount.withdraw(100);//免手续
        System.out.println(savingsAccount.getBalance());//1412.99 -100 =1312.99
        savingsAccount.withdraw(100);//免手续
        savingsAccount.withdraw(100);//免手续
        System.out.println(savingsAccount.getBalance());//1412.99 -200 =1112.99
        savingsAccount.deposit(100);//扣手续费
        System.out.println(savingsAccount.getBalance());//1112.99 + 100 = 1212.99 - 1 = 1211.99

    }
}


14.9

在这里插入图片描述

package com.hspedu.homework;

public class Point {
    
    
    private double x;
    private double y;

    public Point(double x, double y) {
    
    
        this.x = x;
        this.y = y;
    }
}

package com.hspedu.homework;

public class LabeledPoint extends Point {
    
    
    //特有属性
    private String label;

    public LabeledPoint(String label, double x, double y) {
    
    
        super(x, y);
        this.label = label;
    }
    //方法
}

package com.hspedu.homework;

public class Homework09 {
    
    
    public static void main(String[] args) {
    
    
        new LabeledPoint("Black",1929,230.07);
    }
}

14.10

在这里插入图片描述

package com.hspedu.homework;

public class Doctor {
    
    
    //属性
    //{name, age, job, gender, sal}
    private String name;
    private int age;
    private String job;
    private char gender;
    private double sal;
    //5个参数的构造器

    public Doctor(String name, int age, String job, char gender, double sal) {
    
    
        this.name = name;
        this.age = age;
        this.job = job;
        this.gender = gender;
        this.sal = sal;
    }

    //方法
    //相应的getter()和setter()方法

    public String getName() {
    
    
        return name;
    }

    public void setName(String name) {
    
    
        this.name = name;
    }

    public int getAge() {
    
    
        return age;
    }

    public void setAge(int age) {
    
    
        this.age = age;
    }

    public String getJob() {
    
    
        return job;
    }

    public void setJob(String job) {
    
    
        this.job = job;
    }

    public char getGender() {
    
    
        return gender;
    }

    public void setGender(char gender) {
    
    
        this.gender = gender;
    }

    public double getSal() {
    
    
        return sal;
    }

    public void setSal(double sal) {
    
    
        this.sal = sal;
    }

    //重写父类(Object)的equals()方法:public boolean equals(Object obj),并判断测试类中创建的两个对象是否相等。相等就是判断属性是否相同
    public boolean equals(Object obj) {
    
    
        //判断两个比较对象是否相同
        if (this == obj) {
    
    
            return true;
        }
        //判断obj 是否是 Doctor类型或其子类
        //过关斩将 校验方式
        if (!(obj instanceof Doctor)) {
    
     //不是的话
            return false;
        }

        //向下转型, 因为obj的运行类型是Doctor或者其子类型
        Doctor doctor = (Doctor)obj;
        return this.name.equals(doctor.name) && this.age == doctor.age &&
                this.gender == doctor.gender && this.job.equals(doctor.job) && this.sal == doctor.sal;

    }
}

package com.hspedu.homework;

public class Homework10 {
    
    
    public static void main(String[] args) {
    
    
        //测试
        Doctor doctor1 = new Doctor("jack", 20, "牙科医生", '男', 20000);
        Doctor doctor2 = new Doctor("jack", 21, "牙科医生", '男', 20000);

        System.out.println(doctor1.equals(doctor2));//T
    }
}

14.11

在这里插入图片描述

14.12 说出==和equals的区别

在这里插入图片描述

14.13

在这里插入图片描述

package com.hspedu.homework.homework13;
/*
抽取一个父类Person类,将共同属性和方法放到Person类
 */
public class Person {
    
    //父类
    private String name;
    private char gender;
    private int age;
    //方法

    public Person(String name, char gender, int age) {
    
    
        this.name = name;
        this.gender = gender;
        this.age = age;
    }

    public String getName() {
    
    
        return name;
    }

    public void setName(String name) {
    
    
        this.name = name;
    }

    public char getGender() {
    
    
        return gender;
    }

    public void setGender(char gender) {
    
    
        this.gender = gender;
    }

    public int getAge() {
    
    
        return age;
    }

    public void setAge(int age) {
    
    
        this.age = age;
    }

    //编写一个play 方法, 把共有的输出内容写到父类
    public String play() {
    
    
        return name + "爱玩";
    }
    //返回一个基本信息
    /*
    姓名:张飞
    年龄:30
    性别:男
     */
    public String basicInfo() {
    
    
        return "姓名: " + name + "\n年龄: " + age + "\n性别: " + gender;
    }

    @Override
    public String toString() {
    
    
        return "Person{" +
                "name='" + name + '\'' +
                ", gender=" + gender +
                ", age=" + age +
                '}';
    }
}

package com.hspedu.homework.homework13;

/*
Student类有名称(name),性别(sex),年龄(age),学号(stu_id),
做合理封装,通过构造器在创建对象时将4个属性赋值。

学生需要有学习的方法(study),在方法里写生“我承诺,我会好好学习。”
 */
public class Student extends Person{
    
     //
    //属性

    private String stu_id;
    //方法
    public Student(String name, char gender, int age, String stu_id) {
    
    
        super(name, gender, age);
        this.stu_id = stu_id;
    }

    public String getStu_id() {
    
    
        return stu_id;
    }

    public void setStu_id(String stu_id) {
    
    
        this.stu_id = stu_id;
    }

    //我承诺,我会好好学习
    public void study() {
    
    
        System.out.println(getName() + "承诺,我会好好学习 老韩讲的 java");
    }

    /**
     * 学生爱玩足球
     * @return
     */
    @Override
    public String play() {
    
    
        return super.play() + "足球";
    }

    //编写一个输出信息的方法,这样体现封装
    public void printInfo() {
    
    
        System.out.println("学生的信息:");
        System.out.println(super.basicInfo());
        System.out.println("学号: " + stu_id);
        study();//组合, 变化万千
        System.out.println(play());
    }

    @Override
    public String toString() {
    
    
        return "Student{" +
                "stu_id='" + stu_id + '\'' +
                '}' + super.toString();
    }
}

package com.hspedu.homework.homework13;

/*
写一个Teacher类,Teacher类有名称(name),性别(sex),年龄(age),工龄(work_age),
做合理封装,通过构造器在创建对象时将4个属性赋值
 */
public class Teacher extends Person {
    
    
    //属性
    private int work_age;
    //方法

    public Teacher(String name, char gender, int age, int work_age) {
    
    
        super(name, gender, age);
        this.work_age = work_age;
    }


    public int getWork_age() {
    
    
        return work_age;
    }

    public void setWork_age(int work_age) {
    
    
        this.work_age = work_age;
    }

    //教师需要有教学的方法(teach),在方法里写上“我承诺,我会认真教学。
    public void teach() {
    
    
        System.out.println(getName() + "承诺,我会认真教学 java...");
    }
    /**
     * 老师爱玩象棋
     */
    @Override
    public String play() {
    
    
        return super.play() + "象棋";
    }
    //输出信息方法
    public void printInfo() {
    
    
        System.out.println("老师的信息:");
        System.out.println(super.basicInfo());
        System.out.println("工龄: " + work_age);
        teach();
        System.out.println(play());
    }

    @Override
    public String toString() {
    
    
        return "Teacher{" +
                "work_age=" + work_age +
                '}' + super.toString();
    }
}

package com.hspedu.homework.homework13;

public class Homework13 {
    
    
    public static void main(String[] args) {
    
    

        //测试老师
        Teacher teacher = new Teacher("张飞", '男', 30, 5);

        teacher.printInfo();

        //测试
        Student student = new Student("小明", '男', 15, "00023102");
        System.out.println("-----------------------------------");
        student.printInfo();//封装


        //定义多态数组,里面保存2个学生和2个教师,要求按年龄从高到低排序
        Person[] persons = new Person[4];
        persons[0] = new Student("jack", '男', 10, "0001");
        persons[1] = new Student("mary", '女', 20, "0002");
        persons[2] = new Teacher("smith", '男', 36, 5);
        persons[3] = new Teacher("scott", '男', 26, 1);

        //创建对象
        Homework13 homework13 = new Homework13();
        homework13.bubbleSort(persons);

        //输出排序后的数组
        System.out.println("---排序后的数组-----");
        for(int i = 0; i < persons.length; i++) {
    
    
            System.out.println(persons[i]);
        }

        //遍历数组,调用test方法
        System.out.println("=======================");
        for (int i = 0; i < persons.length; i++) {
    
    //遍历多态数组
            homework13.test(persons[i]);
        }

    }

    //定义方法,形参为Person类型,功能:调用学生的study或教师的teach方法
    //分析这里会使用到向下转型和类型判断
    public void test(Person p) {
    
    
        if(p instanceof Student) {
    
    //p 的运行类型如果是Student
            ((Student) p).study();
        } else if(p instanceof  Teacher) {
    
    
            ((Teacher) p).teach();
        } else {
    
    
            System.out.println("do nothing...");
        }
    }

    //方法,完成年龄从高到底排序
    public void bubbleSort(Person[] persons) {
    
    
        Person temp = null;
        for (int i = 0; i < persons.length - 1; i++) {
    
    
            for (int j = 0; j < persons.length - 1 - i; j++) {
    
    
                //判断条件, 注意这里的条件可以根据需要,变化
                if(persons[j].getAge() < persons[j+1].getAge()) {
    
    
                    temp = persons[j];
                    persons[j] = persons[j + 1];
                    persons[j + 1] = temp;
                }
            }
        }
    }

}

14.14

在这里插入图片描述

14.15

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_60766221/article/details/121851563