五、面向对象编程(中级)

五.面向对象编程(中级)

1.IDEA使用技巧和经验(pycharm也类似)
  • 必熟快捷键!自定义可以在file -> settings -> Keymap中设置

    • 删除当前行(自定义) ctrl + D

    • 剪切当前行 ctrl + X

    • 复制当前行 (自定义) Ctrl + alt +向下光标

    • 补全代码 alt+/

    • 导入该行需要的类 先配置auto import 然后使用alt+enter

    • 快速格式化代码 Ctrl + alt + L

    • 快速运行程序 (自定义) alt +R

    • 生成构造器 alt +insert

    • 查看类的层级关系 ctrl +H (试试)

    • 定位到方法 光标放方法上,ctrl +B

    • 自动分配变量名 在分配空间后边.var (试试)

  • 模版

    • 可以在file -> settings -> editor -> Live templates中查看有哪些模版以及自定义模板
2.包
  • 包的命名
    • 一般是小写字母+小圆点
    • com.公司名.形目名.业务模块名
  • 常用的包
    • java.lang 基本包,默认引入
    • java.util 系统提供的工具包,工具类,使用Scanner
    • java.net 网络包
    • java.awt Java界面开发,GUI
import java.util.Scanner;
import java.util.*;
//使用哪个类就导入哪个,不要全部导入
  • package的作用是声明当前类所在的包,需要放在类的最上面;import语句放到package下边,一个类中只能有一个package
3.访问修饰符
  • 类别介绍
    • public:对外公开
    • protected :对子类和同一个包中的类公开
    • 默认 :向同一个包的类公开
    • private :只有类本身可以访问
  • 在这里插入图片描述
  • 修饰符可以修饰类中的属性、方法以及类
    • 四种修饰符都可以修饰属性方法
    • 类只能用默认和public修饰!!!
4.封装
  • 好处

    • 隐藏实现细节,用方法调用即可
    • 可以对数据进行验证,保证安全合理
  • 封装实现步骤

    • 先对属性私有化(不能直接修改属性)

    • 提供一个公共的set方法,用于对属性判断并赋值

    • 提供一个公共的get方法,用于获取属性的值

    • IDEA使用快捷构造set和get方法:alt+fn+insert

  • 封装会在修改是进行保护和判断,但是使用构造器初始化一个对象时会越过set方法的保护和判断,所以可以把set封装到构造器中

public Person(String name, int age, double salary) {
//        this.name = name;
//        this.age = age;
//        this.salary = salary;
        //我们可以将set方法写在构造器中,这样仍然可以验证
        setName(name);
        setAge(age);
        setSalary(salary);
}
5.继承
  • **好处:**代码的可复用性提高了
  • 子类继承了所有的属性和方法,非私有的属性和方法可以直接访问,但是私有的属性和方法不能在子类直接访问,要通过父类提供公共的方法访问
  • 子类必须调用父类的构造器,完成父类的初始化
  • 当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器,如果父类没有提供无参构造器,则必须在子类构造器中用super去指定父类的哪个构造器完成对父类初始化工作,否则编译会报错
public class Sub extends Bash{
    public Sub() {
        super();//这行语句调用父类Bash的无参构造器,不写系统会自己默认调用,写不写一样
        System.out.printf("sub()...");
    }
}
  • 如果希望指定去调用弗雷德额某个构造器,则显式的调用一下

super(参数列表)

  • super使用时必须放在构造器第一行

  • super()和this()都只能放在构造器的第一行,因此这两个方法不能共存在一个构造器

  • java所有类都是Object,是所有类的基类(使用ctrl+H查看继承关系)
    在这里插入图片描述

  • 父类构造器的调用不限于直接父类(即上一级父类),将会一致往上追溯直到Object类(顶级父类)

  • (star)子类在java中最多只能 继承一个父类,即java中是单继承机制,那么怎么让A类同时继承B类和C类?可以先用B继承C,再用A继承B

  • 不能滥用继承,子类父类之间必须满足is-a的逻辑关系

  • 继承的本质分析(重要,韩顺平293集)

    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);//在age不是私有的时候可以访问,返回的就是39
            //System.out.println(son.getAge());//在age是私有的时候,使用公有的get调用,返回的就是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 = "大头儿子";
    }
    
    • 上述代码内存图

    在这里插入图片描述

6.super、方法重写

super

  • super代表父类的引用,用于访问父类的属性、方法、构造器
  • 基本语法:
    • 访问父类除了private的属性 super.属性
    • 访问父类除了private的方法 super.方法(参数列表)
    • 访问父类的构造器 super(参数列表) 只能放在构造器的第一行
  • 调用父类构造器的好处
  • super的访问不限于父类,也可以调用爷爷类,super遵循就近原则,但如果父类中的是private属性或者方法,则直接截断,不会再继续调用爷爷类的public属性和方法

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

方法重写/覆盖(override)

  • **定义:**子类有一个方法和父类的某个方法的名称、返回类型、参数一样,就说子类的这个方法覆盖了父类的方法
  • 子类方法的返回类型和父类方法的返回类型一样,或者是父类返回类型的子类,比如父类返回Object,子类返回String就是可以的,反过来就不行
  • 子类方法不能缩小父类方法的访问权限,但是放大可以(子类访问权限>=父类访问权限

方法重写、重载的区别
在这里插入图片描述

7.多态
  • 多态是指方法或者对象具有多种形态,多态是建立在封装和集成的基础之上的

  • 方法的多态

    • 重写和重载就体现了多态
  • 对象的多态(重难点

    • 编译类型看定义时=左边,运行类型看=号右边
    //假设Dog继承于父类Animal
    Animal animal = new Dog();
    //此时编译类型是Animal,运行类型是Dog
    
    • 一个对象的编译类型和运行类型可以不一致
    • 编译类型在定义对象时就确定了,不能再改变
    • 运行类型是可以变化的
    • 访问属性看编译类型,访问方法看运行类型
  • 多态的细节

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

    • 向上转型

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

      •   Animal animal = new Dog();
        
      • 特点:(1)对象可以调用父类中的所有成员(需要遵守访问权限) (2)对象不能调用子类中的特有成员 (3)最终运行效果看子类中的具体实现

    • 向下转型

      •   Animal animal = new Dog();
          Dog dog = (Dog) animal;//可以跟强制转换进行类比
        
      • 只能强转父类的引用,不能强转父类的对象

      • 要求父类的引用必须指向的是当前目标类型的对象

      • 当向下转型后,可以调用子类类型中所有的成员

  • java的动态绑定机制(重要

    • 当调用对象方法的时候,该方法会和该对象的内存地址/运行类型绑定(不管当前执行的方法是编译类型里的还是运行类型里的,只要再递归调用另一个方法,就去运行类里面找
    • 当调用对象属性时,没有动态绑定机制,哪里声明,哪里使用 (当前需要用的属性声明在哪个类中,就用哪个类的,不用考虑是编译类型还是运行类型。也就是说属性没有动态绑定机制
  • 多态的应用

    • 多态数组

      • 指的是数组的定义类型(编译类型)为父类类型,而里边实际保存的元素类型为子类类型(运行类型)
      • 应用实例:现有一个继承结构如下,Person<-Student ,Person<-Teacher
        • 要求创建1个Person对象、2个Student 对象和2个Teacher对象, 统一放在数组中,并调用每个对象say方法(三个类都有)
        • 要求访问Student 对象和Teacher对象独有的方法(Student 中有score() ,Teacher中有salary())(由多态的向上转型可知,如果不对对象执行操作,直接调用子类中特有方法,是找不到方法的,需要先进行向下转型)
      //向上转型
      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("你的类型有误, 请自己检查...");
          }
      }
      
    • 多态参数

      • 方法定义的形参类型为父类类型,实参类型允许为子类类型
8.Object详解
  • 属于java.lang包(默认引入的)

  • 该类下的几个方法

    • equals()

      • ==既可以判断基本类型(值是否相等)、也可以判断引用类型(地址是不是相等,是不是一个对象)
      • equals只能用于判断引用类型,也就是是否指向同一个地址空间
      • 如果想判断两个对象内的值是否完全相等,可以重写equals方法(源码String中已经把equals重写了)
    • hashCode()

      • 返回该对象的哈希码值
      • 结论(后边会详细讲)
        • 为了提高哈希结构的容器的效率
        • 两个引用,如果指向的是同一个对象,则哈希值肯定是一样的
        • 两个引用,如果指向的是不同对象,则哈希值是不一样的
        • 哈希值主要根据地址号来的!不能完全将哈希值等价于地址
        • 后面在集合中,需要hashcode的话,也会重写
    • toString()

      • 默认返回全类名+@+哈希值的十六进制
      //源码
      //getClass().getName()返回类的全类名(包名+类名)
      public String toString() {
                  return getClass().getName() + "@" + Integer.toHexString(hashCode());
              }
      
      • 可以重写toString方法,实现自己想要的输出
9.断点调试
  • F7 跳入
  • F8 跳过
  • shift+F8 跳出
  • F9 下一个断点(断点可以在debug的过程中设置)
  • 23
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值