Contents

  1. IDEA快捷键
  2. Package:包
  3. 访问修饰符
  4. OOP三大特性之封装
  5. OOP三大特性之继承
  6. OOP三大特性之多态
  7. super关键字
  8. Overwrite
  9. Object类
  10. 断点调试

IDEA快捷键


删除当前行: CTRL + Y
复制当前行并粘贴: CTRL + D
补全代码行: ALT + /
*导入该行需要的类: ALT + ENTER
快速格式化代码: CTRL + ALT + L
运行: SHIFT + F5
*生成构造器等: CTRL + ALT + INSERT
*查看类的层级关系: CTRL + H
*将光标放在一个方法上,输入 CTRL + B可以定位到具体类。
自动分配变量名\for语句等模板:.var .fori

package

基本介绍

作用:

  1. 区分相同名字的类
  2. 当类很多时,可以很好管理类。
  3. 控制访问范围。

本质:创建不同的文件夹保存类文件。
解释:在com.cagur.a com.cagur.b中都存在Person类,如果在另外一个文件中要使用Person类,就要import 如果带上包名就不用import。但是只能有一个是不带包名的。

包的命名规范

小写字母 + 圆点
一般为com.公司名.项目名.业务模块名

使用细节

  • import java.util.Scanner 只引入这一个类
    • import java.util.* 表示引入这个包下所有类
    • 建议:需要使用哪个类就导入哪个类即可,不要使用*
  • package放在类最上面用来打包,一个类最多有一个package,import放package下

访问修饰符

访问控制修饰符 同类 同包 子类 不同包
public 🆗 🆗 🆗 🆗
protected 🆗 🆗 🆗
无修饰 🆗 🆗
private 🆗

同一个类中,无论什么访问权限都能自由访问。
同一个包中,除了private其它都能访问。

细节

  1. 修饰符支持修饰类的属性、成员方法和类。
  2. 类只能用无修饰和public来修饰。

Encapsulation 封装

定义:数据被保护在内部,隐藏实现细节,只有通过调用提供的方法才能访问。
好处:可以对传入的数据进行验证。

步骤

  1. 将属性设为private
  2. 提供public的set方法,用于判断并赋值。--加入数据验证的业务逻辑。
  3. 提供public的get方法,用于获取属性值。--加入权限判断的业务逻辑。

set方法写在构造器中,仍然可以进行验证数据。

Extend 继承

好处:提高了代码复用性、代码扩展性和维护性。

继承的细节

  1. 继承是全继承。子类继承了父类所有成员,但是private的成员不能直接访问。除非通过父类提供的公共方法访问。
  2. 子类必须调用父类构造器。子类构造器隐藏了: super(); 即调用默认调用父类的无参构造。
  3. 如果父类不提供无参构造器,则必须在子类构造器中用super指定父类的哪个构造器完成对父类的初始化工作!
  4. super必须放在子类构造器的第一行!
  5. super() 和 this() 都只能放构造器第一行,因此不能共存于同一个构造器。
  6. Object是所有类的基类。
  7. 父类构造器的调用不限于直接父类,将一直向上追溯到Object
  8. 单继承机制:子类最多继承一个父类。
  9. 不能滥用继承,必须满足 is a 的关系

继承的本质

建立一个查找关系!
方法区的加载顺序:从父到子。
访问子类方法时候的查找顺序:

  1. 首先看子类是否有该属性。如果有且权限允许,就访问。
  2. 如果子类没有,就看父类是否有这个属性且权限允许,有就访问。
  3. 按照2的逻辑一直找到object
  4. 如果都没有就不行。如果找到其中一步但是访问权限为private,不会继续找,报错。

super关键字

基本介绍

  • super代表父类引用,用于访问父类的属性、方法和构造器。
  • 基本语法:
    • 支持访问父类属性,**无法访问父类的私有属性。**父类方法同理。
    • 对于构造器,只能放到子类构造器的第一条语句。super()

super好处

  • 子类中有和父类的成员重名时,为了访问父类成员,比如通过super。
    • 以寻找某个方法为例,先找本类,如果有就调用,如果没有就找父类。
    • 父类没有继续向上找,直到Object。
    • 如果查找过程中,找到了这个方法但是访问修饰符不允许访问某,则报错
    • 没有找到会提示方法不存在。
  • super访问不限于直接父类,但是遵循就近原则。 继承的本质是建立一种查找关系。

Override重写

  • 子类的方法和父类:方法名相同、返回类型相同、参数相同,就说子类覆盖了父类的方法。
  • 细节;
    • 要求子类方法参数、方法名字和父类完全相同。
    • 子类的返回类型,和父类返回类型一致,或者父类返回类型的子类。
      • 比如父类返回Object,子类可以返回String。
    • 子类不能缩小父类访问权限。
  • 重写和重载的比较
    • 重写:父子类之间的关系。
    • 重载:在本类中,方法名相同,但是参数列表中类型、个数、顺序至少一个不同,同时不要求返回类型相同,没有修饰符的要求。

多态Polymorphic

  • 引入多态:凡是Animal就需要用一个Eat方法,但是Animal的种类很多,不可能对Cat、Dog、Monkey都写Eat方法,代码复用性太差。
  • 基本介绍:
    • 方法多态:
      • 重写:不同参数去调用sum方法,体现了sum方法的多种状态。
      • 重载:每个对象调用自己的eat方法。
    • 多态的核心:类的多态。

对象多态

  • 多态四要素:
    • 一个对象的编译类型和运行类型可以不一致。
    • 编译类型在定义对象的时候就确定了,无法改变
    • 运行类型是可以变化的
    • 在Java中,编译类型看左边,运行类型看右边
  Animal animal = new Dog();//父类引用指向子类对象
	//左边是引用,表示编译类型是Animal。
  //右边表示,运行类型是Dog

	animal = new Cat();
	//编译类型仍然是Animal,运行类型可以改变成为Cat。


  Animal a = new Dog();
  a.cry();//dog cry

  a = new Cat();
  a.cry();
  //cat cry
//演示多态参数
public void feed(Animal animal , Food food){
  sout(animal.getName() + food.getName());
}

多态细节讨论

  • 讨论前提:两个类存在继承关系。

向上转型

  • 本质:父类引用指向子类的对象。
  • 语法:父类引用名 = new 子类型();
    • 例:Object obj = new Cat()
  • 特点:编译类型看左边,运行类型看右边。
    • 可以调用父类中所有成员,但是需要遵循访问权限。
      • 依据:编译阶段能调用哪些成员由编译类型决定
    • 不能调用子类中的特定成员。
    • 最终运行效果看子类的具体体现。
      • 例:假设猫和动物均有eat方法,猫有miao方法,动物有run方法,猫继承动物并进行向上转型。那么,调用eat方法会调用猫的eat,无法调用miao,能调用run

向下转型

  • 语法:子类引用 = (子类类型)父类。
    • Cat cat = (Cat)animal;
  • 细节:
    • 只能强转父类的引用。
    • 要求父类引用必须指向的是当前目标类型的对象。(即animal原来就指向了cat)
    • 向下转型后,可以调用子类的所有成员。
Animal animal = new Cat();
//error
cat.catchMouse();

Cat cat = (Cat)animal; //编译类型和运行类型不变
//success
cat.catchMouse();

属性没有重写,属性看编译类型!

instanceOf比较操作符:看的是运行类型

  • 用法:判断对象是否还有XX类型,或者XX类型的子类型
class Base{}
class Son extends Base{}

Son son = new Son();
son instanceof Son //true
son instanceof Base // true

Base base = new Son();
base instanceof Base //true 运行类型是Base子类
base instanceof Son //true 运行类型是Son

Object obj = new Object();
obj instanceof Base //false 运行类型是Object,不是Base及其子类 

"hello" instanceof Object // true

⭐动态绑定机制

  • 当调用对象方法的时候,该方法会与对象的内存地址/运行类型进行绑定。
  • 当调用对象属性的时候,没有动态绑定机制。

多态应用

多态参数

  • 方法定义的形式参数为父类类型,实参运行传入子类类型。

多态数组

package poly.polyarr;

public class PolyArray {
    public static void main(String[] args) {
        // TODO: 2023/1/4 多态数组
        // 创建2个学生对象,2个老师对象,统一放在数组中
        Person[] persons = new Person[5];
        persons[0] = new Person("jack",50);
        persons[1] = new Student("jack",18,100);
        persons[2] = new Student("smith",20,80);
        persons[3] = new Teacher("scott",30,20000);
        persons[4] = new Teacher("king",25,50000);
        //遍历多态数组说say
        for(int i = 0;i<persons.length;i++){
            System.out.println(persons[i].say());   // 动态绑定
                //person[i]的编译类型是Person。运行类型根据实际决定。
            //如何调用子类的特殊方法呢?--类型判断结合向下转型
            if(persons[i] instanceof Student){
                ((Student)persons[i]).study(); // 向下转型,将person转换成子类引用
            }else if(persons[i] instanceof Teacher){
                ((Teacher)persons[i]).teach();
            }else{
                System.out.println("类型有误请检查");
            }
        }
    }
}