Java笔记——面向对象编程(中级)

面向对象编程(中级)

IntelliJ IDEA

快捷键(Mac版)

  1. 删除当前行 command + backspace
  2. 复制当前行 command + D
  3. 补全代码 option + /
  4. 添加注释和取消注释 command + space + /
  5. 导入该行需要的类 option + enter
  6. 快速格式化代码 option + command + L
  7. 快速运行程序 control + shift + R
  8. 生成构造器等 command + N
  9. 查看一个类的层级关系 control + H
  10. 自动的分配变量名 .var
  11. 定位方法的类 将光标放在方法上 command + click
  12. 模板/自定义模板 Live Templates psvm sout

快捷键(Win版)

File -> Setting -> Keymap

  1. 显示所有快捷键 ctrl + J
  2. 删除当前行 Ctrl + Y
  3. 复制当前行 Ctrl + D
  4. 补全代码 Alt + /
  5. 添加、取消注释 Ctrl + /
  6. 导入该行需要的类 先配置auto import,然后使用Alt + Enter
  7. 快速格式化代码 Ctrl + Alt + L
  8. 快速运行程序 Shift + F10
  9. 生成构造器等 Alt + Insert
  10. 查看一个类的层级(继承)关系 Ctrl + H
  11. 自动的分配变量名 .var Alt+Enter
  12. 定位方法的类 将光标放在方法上 Ctrl + 鼠标左键
  13. 模板/自定义模板 Live Templates psvm sout
  14. 移动当前行 Alt+Shift+
  15. 多行编辑 Alt+ 鼠标拖动
  16. 向后删除 Del

包的三大作用

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

包的基本语法

package 包名; 包的本质 实际上就是创建不同的文件夹/目录来保存类文件

image-20211107214820966 ### 常用的包 * java.lang.* // lang包是基本包,默认引入,不需要再引入 * java.util.* // util包,系统提供的工具包,工具类,例如使用Scanner时需引入 * java.net.* // 网络包,网络开发 * java.awt.* // 是做java的界面开发,GUI

访问修饰符

访问级别 访问控制修饰符 同一类 同一包 子类 不同包
公开 public
受保护 protected ×
默认 × ×
私有 private × × ×

注意事项

  1. 修饰符可以用来修饰类中的属性,成员方法以及类
  2. 只有默认的和public才能修饰类!并遵循上述访问权限的特点
  3. 成员方法的访问规则和属性完全一致

封装

封装介绍

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

封装的理解和好处

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

封装的实现步骤(三步)

  1. 将属性进行私有化private 【不能直接修改属性】
  2. 提供一个公共的set方法,用于对属性判断并赋值
    1
    2
    3
    4
    public void setXxx(类型 参数名) { // Xxx表示某个属性
    //加入数据验证的业务逻辑
    属性 = 参数名;
    }
  3. 提供一个公共的get方法,用于获取属性的值
    1
    2
    3
    public 数据类型 getXxx() { // 权限判断,Xxx的某个属性
    return xx;
    }

封装与构造器

构造器中调用set方法,实现数据验证逻辑

继承

当多个类存在相同的属性(变量)和方法时,可以从这些类中抽象出父类,在父类中定义这些相同的属性和方法,所有子类不需要重新定义这些属性和方法,只需要通过extends来声明继承父类即可。 ### 继承的基本语法

1
2
3
class 子类 extends 父类 {

}
1. 子类自动拥有父类定义的属性和方法 2. 父类又叫超类、基类 3. 子类又叫派生类

继承的使用细节

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

继承的内存布局

image-20211109202905373

多态 Polymorphic

多态基本介绍

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

多态的具体体现

  1. 方法的多态: 重写和重载体现多态
  2. 对象的多态:
    • 一个对象的编译类型和运行类型可以不一致
    • 编译类型在定义对象时就确定了,不能改变
    • 运行类型时可以变化的
    • 编译类型看定义时=的左边,运行类型看=的右边
      1
      2
      Animal animal = new Dog(); // animal编译类型是Animal,运行类型是Dog
      animal = new Cat(); // animal的运行类型变成了Cat,编译类型仍然是Animal
  3. 使用多态机制,统一管理主人喂食问题
    1
    2
    3
    public void feed(Animal animal, Food food) {
    System.out.println(animal.getName() + " " + food.getName());
    }

注意细节

  1. 多态的前提是:两个对象(类)存在继承关系
  2. 多态的向上转型
    • 本质:父类引用指向子类对象 Object obj = new Cat();
    • 特点:可以调用父类中的所有成员(需遵守访问权限),不能调用子类的特有成员,最终运行效果看子类的具体实现。
  3. 多态的向下转型
    • 语法:子类类型 引用名 = (子类类型) 父类引用; Cat cat = (Cat) animal;
    • 特点:只能强转父类的引用,不能强转父类的对象;要求父类的引用必须指向的是当前目标类型;可以调用子类类型中的所有成员
  4. 属性/成员变量没有重写之说!属性的值看编译类型
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    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;
    }
  5. instanceOf比较操作符,用于判断对象的运行类型是否为xx类型或xx类型的子类型
  6. Java的动态绑定机制(重要)
    • 当调用对象方法的时候,该方法会和该对象的内存地址/运行类型绑定
    • 当调用对象属性时,没有动态绑定机制,哪里声明,那里使用
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      class A {
      public int i = 10;
      public int sum() {
      return getI() + 10;
      }
      public int sum1() {
      return i + 10;
      }
      public int getI() {
      return i;
      }
      }

      class B extends A {
      public int i = 20;
      // public int sum() {
      // return i + 20;
      // }
      public int getI() {
      return i;
      }
      // public int sum1() {
      // return i + 10;
      // }
      }

      // main方法中
      // A是a的编译类型,B是a的运行类型
      A a = new B(); // 向上转型
      System.out.println(a.sum()); // 40 注释掉B的sum方法后---> 30
      Systtem.out.println(a.sum1()); // 30 ---> 20

多态的应用

  1. 多态数组 数组的定义类型为父类类型,里面保存的实际元素类型为子类类型 Person[] persons = new Person[5]; persons[0] = new Student("jack", 18, 100); if(person[i] instanceOf Student) ((Student) person[i]).study();
  2. 多态参数 方法定义的形参类型为父类类型,实参类型允许为子类类型

Super

super代表父类的引用,用于访问父类的属性、方法、构造器 ### 基本语法 1. 访问父类的属性,但不能访问父类的private属性 super.属性名; 2. 访问父类的方法,不能访问父类的private方法 super.方法名(参数列表); 3. 访问父类的构造器,只能用在构造器的第一句,只能出现一句! super(参数列表);

使用细节

  1. 调用父类的构造器的好处(分工明确,父类属性由父类初始化,子类属性由子类初始化)
  2. 当子类中有和父类中的成员(属性和方法)重名时,为了访问父类的成员,必须通过super。如果没有重名,使用super、this、直接访问是一样的效果!
  3. 如果多个基类(上级类)中都用同名的成员,使用super访问遵循就近原则。

super和this的比较

image-20211109215804994

方法重写/覆盖 Override

方法重写就是子类有一个方法,和父类的某个方法的名字、返回类型、参数一样,那么我们就说子类的这个方法覆盖了父类的方法 ### 使用细节 1. 子类的方法的形参列表,方法名,要和父类方法的形参列表,方法名完全一致。 2. 子类方法的返回类型和父类方法的返回类型一样,或者是父类返回类型的子类;比如 父类返回类型是Object,子类方法返回类型是String。 3. 子类方法不能缩小父类方法的访问权限。 void A() {} public void A() {}

方法重写和重载的比较

image-20211109222337091

Object类详解

equals()

  1. ==equals的对比
  • ==是一个比较运算符,既可以判断基本类型(值),又可以判断引用类型(地址)
  • equals只能判断引用类型,默认判断的是地址是否相等,子类往往重写该方法,用于判断内容是否相等。

hashCode()

  1. 提高具有哈希结构的容器的效率!
  2. 两个引用,如果指向的是同一对象,则哈希值肯定一样
  3. 两个引用,如果指向的是不同的对象,则哈希值是不一样的
  4. 哈希值主要是根据地址号来的,不能完全将哈希值等价于地址

toString()

  1. 基本介绍 默认返回:全类名 + @ + 哈希值的十六进制,子类往往重写toString方法,用于返回对象的属性信息。
    1
    2
    3
    public String toString() {
    return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }
  2. 重写toString方法,打印对象或拼接对象时,都会自动调用该对象的toString形式。
  3. 当直接输出一个对象时,toString方法会被默认的调用。

finalize()

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

断点调试

  1. Step over 逐行运行
  2. Step into 进入方法 Step out 运行完当前方法
  3. Resume 运行到下一个断点

Java笔记——面向对象编程(中级)
https://nessaj7.github.io/2021/11/07/3ac8577c686b.html
作者
kuhn
发布于
2021年11月7日
许可协议