10-Java面向对象中级

  • 区分相同名字的类
  • 当类很多时,包可以很好的管理类
  • 控制访问范围

包的基本语法
package com.hspedu;

包的本质就是通过创建不同的文件夹来创建不同的类文件

  • 快速入门
package com.use;

//import com.xiaoqiang.Dog;

public class Test {

    public static void main(String[] args) {
        com.xiaoqiang.Dog dog = new com.xiaoqiang.Dog();
        System.out.println(dog);

        com.xiaoming.Dog dog1 = new com.xiaoming.Dog();
        System.out.println(dog1);

    }
}

  • 包的命名规则
  • 声明包放在最上面
package com.hapedu;

//import java.util.Scanner;
//import java.util.*;

import java.util.Arrays;

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

访问修饰符


package com.hspedu.modifier;

public class A {
    // 四个属性,有四类访问修饰符,分别使用不同的访问修饰符修饰
    public int n1 = 100;
    protected  int n2 = 200;
    int n3 = 300;
    private int n4 = 400;

    public void m1(){
        // 该方法可以访问4个属性
        System.out.println("n1=" + n1 + " n2 = " + n2 + " n3=" + n3 + " n4=" + n4);
    }
    protected void m2(){

    }

    void m3(){

    }
    private  void m4(){

    }

}

封装

  • 封装就是把抽象出来的数据【属性】和对数据的操作【方法】封装在一起,数据被保护在内部,程序的其他部分只有通过授权的【方法】,才能对数据进行操作
  • 对电视机的操作就是典型的封装
  • 封装带来的好处
    1.可以隐藏实现细节和方法(连接数据库)<-调用(传入参数.....)
    2.可以对数据进行验证,保证安全合理性
  • 封装的实现步骤
  • 封装的快速入门
package com.hspedu.encap;

public class Encapsu01 {
    public static void main(String[] args) {
        Person person = new Person();
        person.setName("jackagesf");
        person.setAge(3000);
        person.setSalary(1200);
        System.out.println(person.info());

    }
}
/*

 */
class Person{
    public String name;
    private int age;
    private  double salary;
    // 自己写太慢,可以使用快捷键 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=" + salary;
    }
}
package com.hspedu.encap;

public class Encapsu01 {
    public static void main(String[] args) {
        Person person = new Person();
        person.setName("jackagesf");
        person.setAge(3000);
        person.setSalary(1200);
        System.out.println(person.info());

        // 如果我们使用构造器
        Person smith = new Person("smith", 200, 15000);
        System.out.println(smith.info());
    }
}
/*

 */
class Person{
    public String name;
    private int age;
    private  double salary;
    public Person(){

    }
    // 有三个属性的构造器
    public Person(String name, int age, double salary) {
//        this.name = name;
//        this.age = age;
//        this.salary = salary;
        setName(name);
        setAge(age);
        setSalary(salary);
    }
    // 自己写太慢,可以使用快捷键 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=" + salary;
    }
}
  • 封装练习:定义两个类,Account对姓名,余额,密码进行限定,并且要求不能在外面进行修改
package com.hspedu.encap;

public class Account {
    private String name;
    private double remainder;
    private String password;
    // 提供两个构造器
    public Account(){

    }

    public Account(String name, double remainder, String password) {
        setName(name);
        setRemainder(remainder);
        setPassword(password);
    }

    public void setName(String name) {
        if(name.length() >=2 && name.length() <= 4){
            this.name = name;
        }
        else {
            System.out.println("name在4-6之间");
            this.name = null;
        }

    }

    public void setRemainder(double remainder) {
        if(remainder > 20){
            this.remainder = remainder;
        }
        else {
            System.out.println("余额必须大于20,否则默认为0");
            this.remainder = 0;
        }

    }

    public void setPassword(String password) {
        if(password.length() == 6){
            this.password = password;
        }
        else{

            System.out.println("密码长度为6位,否则默认为123456");
            this.password = "123456";
        }

    }

    public String getInfo(){
        return "name=" + name + " remainder=" + remainder + " password=" + password;
    }
}

继承

  • 为什么需要继承?


  • 快速入门

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_;

public class Graduate extends Student{
    public void testing(){
        System.out.println("大学生" + name + "正在考大学数学.....");
    }
}
  • 继承的优势

  • 代码的复用性提高了

  • 代码的扩展性和维护性提高了

  • 继承的细节

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

    如果父类的方法是私有的,但是爷爷的类是公有的,依然没有办法访问
package com.hspedu.extend_;

import java.util.StringTokenizer;

/**
 * 继承的本质
 */
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);
        System.out.println(son.getAge());
        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 = "大头儿子";
}
  • 练习1 输出结果是
package com.hspedu.extend_.exercise;

public class ExtendsEx01 {
    public static void main(String[] args) {
        B b = new B();


    }

}

class A {
    A() {
        System.out.println("a");
    }

    A(String name) {
        System.out.println("a name");
    }
}

class B extends A {
    B() {
        this("abc");
        System.out.println("b");
    }

    B(String name) {
//        super();
        System.out.println("b name");
    }
}
  • 练习2 输出内容是多少?
package com.hspedu.extend_.exercise;

public class ExtendsEx03 {
    public static void main(String[] args) {
        PC pc = new PC("intel", 16, 500, "IBM");
        pc.printInfo();
    }

}

class Computer{
    String cpu;
    int memory;
    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;
    }
}

class PC extends Computer{

    String brand;

    public PC(String cpu, int memory, int disk, String brand) {
        super(cpu, memory, disk);
        this.brand = brand;
    }

    public void printInfo(){
        System.out.println("PC信息=");
//        System.out.println(cpu);

        System.out.println(getDetails() + " brand=" + brand);
    }
}
class NotePad extends Computer{
    String color;

    public NotePad(String cpu, int memory, int disk, String color) {
        super(cpu, memory, disk);
        this.color = color;
    }

    public void getInfo(){
        System.out.println(getDetails() + " NotePad Color=" + color);
    }
}
  • super关键字
    super 代表父类的引用,用于访问父类的属性、方法、构造器

  • super给编程带来的好处
    1.super给编程带来的好处(分工明确,父类的属性由父类初始化,子类的属性由子类初始化)
    2.当子类中和父类的成员(属性和方法)重名,为了访问父类的成员,必须通过super,如果没有重名,使用super,this,直接访问是一样的效果

  • 方法的重写
    子类的方法和父类名称,反馈类型,参数一样,重写

  • 方法重写的细节

多态

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

  • 多态的具体体现

  • 方法的多态,就是之前讲的重载和重写

  • 多态的具体体现

  • 多态的注意事项和细节讨论
    多态的前提是:两个类存在继承关系
    多态向上转型

package com.hspedu.poly_.detail;

public class PolyDetail {
    public static void main(String[] args) {
        // 向上转型,父类的引用指向了子类的对象
        Animal animal = new Cat();


        //可以访问父类的所有成员(遵守访问权限
        // 但是不能调用子类的特有成员
        // 因为在编译阶段,能调用哪些成员是有编译类型决定的
//        animal.catchMouse();
        // 最终的运行效果还要看子类的实现,先找子类,然后找父类
        animal.eat();
        animal.run();

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

}

  • 多态的向下转型
  • 属性没有重写之说,属性直接看编译类型
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);


    }
}


class Base {
    int count = 10;
}

class Sub extends Base{
    int count = 20;
}
  • instanceOf 是看运行类型是否是对象的类型或者子类

Java的动态绑定机制


多态的时候如果在父类中找方法的时候,存在父类和子类的方法,此时调用运行类型/内存地址的方法,即子类的方法

  • 多态的运用
    1.多态数组
package com.hspedu.poly_.polyarr_;

import com.use.Test;

public class PolyArr {
    public static void main(String[] args) {
        // 现在有一个继承结构如下,统一放入数组
        Person[] persons = new Person[5];
        persons[0] = new Person("jack", 20);
        persons[1] = new Student("micoo", 18, 100);
        persons[2] = new Student("smith", 17, 30);
        persons[3] = new Teacher("scott", 30, 20000);
        persons[4] = new Teacher("king", 50, 250000);

        // 循环遍历数组
        for(int i = 0; i< persons.length; i++){
            // 编译类型是Person,运行类型是实际情况
//            System.out.println(persons[i].say());
            // 判断persons的运行类型是否是Student
            if(persons[i] instanceof Student){
                Student student = (Student)persons[i]; // 向下转型
                student.study();
                // 也可以一条语句搞定,((Student)persons[i]).study()
            }
            else if(persons[i] instanceof Teacher){
                ((Teacher)persons[i]).teach();
            }
            else if(persons[i] instanceof Person){
                continue;
            }
            else {
                System.out.println("你的类型有误");
            }
        }


    }
}

2.多态参数
方法定义的形参类型为父类类型,实参类型允许为子类类型

package com.hspedu.poly_.polypara_;

import com.sun.corba.se.spi.orbutil.threadpool.Work;

public class PolyPara {
    public static void main(String[] args) {
        Worker tom = new Worker("tom", 1000);
        Manager mick = new Manager("Mick", 2000, 600);
        PolyPara polyPara = new PolyPara();
        polyPara.showEmAnnual(tom);
        polyPara.showEmAnnual(mick);

        polyPara.testWork(tom);
        polyPara.testWork(mick);


    }

    public void showEmAnnual(Employee e){
        System.out.println(e.getAnnual());
    }

    public void testWork(Employee e){
        if (e instanceof Worker){
            ((Worker) e).work();
        }
        else if(e instanceof Manager){
            ((Manager) e).manage();
        }
        else{
            System.out.println("类型不对");
        }

    }
}

Object类详解

  • equals 和 == 的对比
    == 是一个比较运算符,既可以判断基本类型,也可以判断引用类型,判断基本类型是判断值是否相等,如果判断引用类型,则判断地址是否相等
    equals 是Object类的方法,只能判断引用类型,但是子类中往往重写该方法,用于判断类型是否相等

HashCode

返回对象的哈希码值,支持此方法是为了提高哈希表的性能

toString

默认返回:全类名【包名+类名】+@+哈希值的16进制

finalize

断点调试

零钱通项目

package com.hspedu.smallchange;
import java.text.SimpleDateFormat;
import java.util.Scanner;
import java.util.Date;

public class SmallChangeSys {

    // 化繁为简,先死后活
    // 1.先完成显示菜单,给出选择菜单,给出相应提示
    // 2.完成零钱通明细
    // 3.收益入账
    // 4.完成消费
    public static void main(String[] args) {
        // 定义相关的变量
        boolean loop = true;
        Scanner scanner = new Scanner(System.in);
        String key = "";

        //2.完成零钱通明细
        // 1,可以把收益入账和消费,保存到数组,2.可以使用对象,3.可以使用String拼接
        String detail = "------------------零钱通明细------------------";

        // 3.收益入账,入账了多少钱
        // 思路:定义新的变量,完成功能驱动我们增加新的变量和代码
        double money = 0;
        double balance = 0;
        Date date = null; // date是日期类型
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");

        // 4.消费增加变量
        // 定义新的变量
        String note = "";

        // 退出
        // 一段代码一个功能

        // 改进
        // 收益入账,
        do{
            System.out.println("\n==================零钱通菜单==================");
            System.out.println("\t\t\t1 零钱通明细");
            System.out.println("\t\t\t2 收益入账");
            System.out.println("\t\t\t3 消   费");
            System.out.println("\t\t\t4 退   出");

            System.out.println("请选择(1-4):");
            key = scanner.next();

            // 使用switch分支结构
            switch (key){
                case "1":

                    System.out.println(detail);
                    break;
                case  "2":
                    System.out.println("收益入账金额:");
                    money = scanner.nextDouble();
                    // money 的值范围应该校验一下 一会在完善
                    // 找到不正确的金额,给出提示,直接break
                    if(money <= 0){
                        System.out.println("收益入账需大于0");
                        break;
                    }

                    balance += money;
                    // 拼接收益入账信息到details
                    date = new Date(); // 获取当前日期
//                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");

                    detail += "\n收益入账\t+" + money + "\t" + sdf.format(date) + "\t" + balance;

                    break;
                case "3":
                    System.out.println("消费金额:");
                    money = scanner.nextDouble();
                    // 范围校验
                    // 找不到不正确的情况
                    if(money <= 0 || money > balance){
                        System.out.println("你的消费金额应该在 0-" + balance);
                        break;
                    }
                    System.out.println("消费说明:");
                    note = scanner.next();
                    balance -= money;
                    date = new Date(); // 获取当前日期

                    detail += "\n" + note + "\t-" + money + "\t" + sdf.format(date) + "\t" + balance;

                    break;
                case "4":
                    String choice = null;
                    while(true){
                        System.out.println("你确定要退出吗?y/n");
                        choice = scanner.next();
                        if("y".equals(choice) || "n".equals(choice)){
                            break;
                        }
                    }
                    if("y".equals(choice)){
                        loop = false;
                    }

                    break;
                default:
                    System.out.println("选择有误,请重新选择");
            }

        } while (loop);

        System.out.println("----退出了零钱通项目----");

    }
}

  • 练习01:对person类中的age进行排序
package com.hspedu.homework.homework01;

public class Homework01 {
    public static void main(String[] args) {
        // 初始化person数组
        Person[] persons =  new Person[3];
        persons[0] = new Person("jack",10, "JavaEE工程师");
        persons[1] = new Person("tom",50, "大数据工程师");
        persons[2] = new Person("mary",30, "PHP工程师");

        for(int i = 0; i < persons.length; i++){
            System.out.println(persons[i]);
        }
        // 使用冒泡排序
        Person temp = null;
        for(int i = 0; i < persons.length-1; i++){
            for(int j = 0; j < persons.length - i - 1; j++){
                if(persons[j].getAge() > persons[j+1].getAge()){
                    temp = persons[j];
                    persons[j] = persons[j+1];
                    persons[j+1] = temp;
                }
            }
        }
        for(int i = 0; i < persons.length; i++){
            System.out.println(persons[i]);
        }


    }
}

/*
    定义一个Person类,{name,age, job} 初始化Person对象数组,有3个对象,
    通过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 + '\'' +
                '}';
    }
}
posted @ 2021-12-28 22:14  心远志高  阅读(34)  评论(0编辑  收藏  举报