zoukankan      html  css  js  c++  java
  • 10Java面向对象中级

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

    包的基本语法
    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 + '\'' +
                    '}';
        }
    }
    
  • 相关阅读:
    CF 436D 最小生成树
    HDU 1847 博弈
    ZOJ 3666 博弈 SG函数
    zoj3675 BFS+状态压缩
    HDU 4734 F(x) 数位DP
    HDU 3709 Balanced Number 数位DP
    HDU 3555 数位DP
    HDU 4336 Card Collector
    HDU4340 Capturing a country DP
    CF 351A
  • 原文地址:https://www.cnblogs.com/jly1/p/15743088.html
Copyright © 2011-2022 走看看