Java 笔记

88 阅读8分钟

JAVA 体系课阶段一

概念

interface 定义了一些空的方法,如果要实现这个 interface,就要实现这些方法。
抽象方法 规定它的子类必须有这样一个方法。
注解
封装 继承 多态 接口

5 - Java程序的基本结构

类与包

  • 每个类都处在一个包中,包名由路径名决定。
  • src/main/java 是默认包。
  • java 最小的结构单元是类,类必须放在和它同名的.java文件中。

包的意义

  • 区分同名,但是不同的类。
  • 避免类的命名冲突,将同名类放入不同的包中。
  • 全限定类名
package com.github.hcsp;

public class home {
    com.github.hcsp.pet1.Cat cat1;
    com.github.hcsp.pet1.Cat cat2;
}
package com.github.hcsp;

import com.github.hcsp.pet1.Cat;

public class home {
    Cat cat1;
    com.github.hcsp.pet2.Cat cat2;  // 由于类名相同,所以这里不能再用简单类名。
}

在Java中引用第三方包

  • java.lang 中的类不用导入包,可以直接使用。
  • 第三方包需要在 pom.xml 中声明,然后下载包,再导入和使用。

方法、静态方法与静态成员变量

  • 静态方法可以直接调用,不用通过实例对象。
  • 静态成员变量是属于类的,独立于任何对象。

对象、构造器、成员变量

假如没有声明 constructor,则编译器会自动生成一个。

实例方法与空指针异常

在类中使用成员变量,在不引起歧义的情况下,可以省略 this。

包、类、静态方法、实例方法、静态成员、实例成员总结

包可以看做包裹类的文件夹。
类中没有用 static 声明的方法和变量是实例方法和实例变量。

对象与引用

字符串是引用类型。

6 - IDEA/Maven/调试器的基本使用

IDEA生产力翻倍的快捷键

万⽤键:Alt+Enter
Search everywhere:双击Shift
查看定义:Declaration
查看⽂件:Navigate - File
⾼级查找:Find in Path
快速⽣成:Generate
格式化:Reformat Code
优化导⼊语句:Optimize imports

导航:Navigate - Back/Forward
谁调⽤了这个⽅法:Call Hierarchy
所有的实现类:Implementation
⽂件⼤纲:File Structure
下⼀处错误:Next Highlighted Error
⾼级重命名:Rename
调试器快捷键:F5/F6/F7/F8

在IDEA中使用Git工具查找背锅侠

查找背锅侠:Annotate/Blame
查看当前⽂件的历史版本
⾼级筛选⽅式查找commit记录
显示差异:show diff
Open in GitHub

调试器入门与详解

  • 条件断点(在断点处右键设置条件)

image.png

resume program: 全速运行到下一个断点。

10 - 对象系统基础

构造函数

  • 新建对象的唯⼀途径。
  • 如果没有任何构造器,编译器会暗中帮你⽣成⼀个。
  • 新建过程:
    在堆上分配空间
    执⾏必要的初始化⼯作
    执⾏构造器函数

⽅法的重载

  • 如何区分同名的不同重载⽅法?
    根据参数类型。
  • 参数属于多种类型如何区分?
    类型最匹配优先。
  • 参数为null时可能导致匹配程度一致,如何处理?
    将null强制类型转换。
  • 如何为⽅法提供默认值?
    只能通过重载实现。

构造函数的重载

用 this() 调用构造函数。

public class Cat {
    int age = 1;
    String name = "";

    Cat() {
        this("mimi");
    }
    Cat(String name) {
        this(1, name);
    }
    Cat(int age, String name) {
        this.age = age;
        this.name = name;
    }
}

对象的初始化

  • 必要的初始化⼯作
    静态成员的初始化
    静态初始化块
    成员的初始化
    初始化块

对象的生命周期

  • 如果⼀直新建对象,内存会不会爆?
    可能会
  • 那对象的内存什么时候被回收?
    谁也不知道(内存充足的时候回收得慢,内存不足的时候回收得快)
  • 对象的内存如何被回收?
    不⽤管,垃圾回收器帮你⼲
  • JVM怎么知道哪个对象没有被⽤到?
    通过引⽤链(GC Roots)。最常见的 roots 是方法栈中的方法里的局部变量,以这些变量为起点的引用链中的东西都不是垃圾,其余的是垃圾。

image.png

11 - 面向对象:封装与访问控制

封装及其必要性

  • 什么是封装?
    封装隐藏了内部实现细节,只暴露出接⼝。
  • 不封装会怎么样?
    暴露细节的结果就是⽆法变化。
    软件的演进栗⼦:为原先的属性增加限制。
    软件的演进栗⼦:修改某些属性。

封装的实现

  • 访问控制符
    public 任何⼈都能访问
    protected 只有⼦类可以访问和同⼀个包的可以访问
    package private 只有同⼀个包的类可以访问
    private 只有⾃⼰可以访问
  • JavaBean约定
    所有属性为private
    提供 getter 和 setter 等

设计模式实战:⼯⼚⽅法

  • 使⽤静态⼯⼚⽅法代替构造器
  • 将构造器私有化

类的访问限定符

  • public 任何类都可以访问
  • package private 同⼀个包的类可以访问
    • 包之间是没有⽗⼦关系的
  • private inner class 只能在同⼀个类中访问
  • 了解:Java Platform Module System

设计模式实战:builder模式

函数参数过多时,在传入参数值时可以声明参数名字。

12 - 面向对象:组合与继承

  • 继承的本质是提炼出公⽤代码,避免重复
  • java 是单根继承的

类的结构与初始化顺序

  • ⼦类拥有⽗类的⼀切数据和⾏为
  • ⽗类先于⼦类
  • 必须拥有匹配的构造器
    • super关键字

实例⽅法的重写/覆盖

  • 永远使⽤@Override注解来防⼿残
  • 举个栗⼦
    • String.equals

设计模式实战:模板方法

提供⼀个“模板”,实现可以覆盖模板的全部或者部分

向上/向下转型

  • ⼀个⼦类类型的对象永远是⼀个⽗类类型的对象
    • 正如⼀只猫同时也是⼀只动物,同时也是⼀个对象
    • instanceof 判断类型
    • null instanceof ? == false
  • 因此,当需要⼀个⽗类型时,总可以传递⼀个⼦类型
  • 但是,有的时候你必须进⾏⼀些转型
    • 转型是不安全的
    • 可能会失败

final关键字

  • final声明变量,变量成为不可变的(必须初始化)
    • 局部变量/⽅法参数
    • 成员变量
    • 常量与单例
  • final在⽅法上的声明:禁⽌继承/覆盖/重写此⽅法
  • final在类声明上的使⽤:禁⽌继承此类
    • 继承提供了灵活性,也埋下了隐患
    • 栗⼦:为什么String/Integer等类是final的?

组合

  • 继承:is-a
  • 组合:has-a
  • 实际中,⼆者的界限有时候很难区分
  • 如何操作:不继承,而是直接拿来其它类的方法去用。

13 面向对象:多态

什么是多态

  • 实例⽅法默认是多态的
    • 在运⾏时根据this来决定调⽤哪个⽅法
    • 静态⽅法没有多态
    • 参数静态绑定,接收者动态绑定
      • 换句话说,多态只对⽅法的接收者⽣效
      • ⼜换句话说,多态只选择接受者的类型,不选择参数的类型

设计模式实战:策略模式

  • 策略模式栗⼦:打折策略
  • JDK线程池中的策略ThreadPoolExecutor

多态实战

炒不同的菜的例子,将相同代码写在父类中实现复用。

image.png

14 面向对象:接口与抽象类

抽象类与接口入门

  • 什么时候用抽象类?
    需要复用代码。

抽象类与接口详解与实战

抽象类

  • 不可实例化
  • 可以实例化的东⻄⼀定要补全所有的⽅法体。
  • 可以包含抽象⽅法(不需要方法体) - ⾮private/static(因为抽象方法就是要被继承、被子类实现)
  • 可以包含普通类的任何东⻄

接⼝

  • 接⼝部分的实现了多继承
  • 接⼝不是类
  • 接⼝的扩展
  • 接⼝只代表⼀种功能
  • ⼀个类只能继承⼀个类,但是却能实现若⼲的接⼝

接⼝可以包含什么

  • 若⼲个⽅法(默认public)
  • 若⼲个常量(默认public static final)
  • extends 接⼝
  • 默认⽅法
    • Since Java 8
    • 是⼀种妥协的产物
    • 可以⽤来实现mixin
    • 菱形继承

补充

  • 抽象类继承一个接口,可以不实现接口的方法,留给子类去实现。
  • 对接口中的方法,public、static、final 这些关键字都是多余的(必须是 puclic 非 static 非 final)。
  • 对接口中的成员变量,public、static、final 这些关键字都是多余的(必须是 puclic、static、final)。
  • 接口的默认方法可以在需求变化时给接口新增方法,不影响之前的代码。
  • 抽象类和接口的共同点:
    • 抽象,不可实例化
    • 都可以包含抽象方法
  • 抽象类和接口的不同点:
    • 抽象类可以包含类的一切,接口只能包含受限的成员和方法
    • 抽象类只能单一继承,接口可以多继承,甚至继承多次
  • 实现一个接口代表着一种承诺,承诺这个类有这个接口定义的能力。
  • 继承和接口都体现了多态。

实现一个文件过滤器

内部类详解

  • ⽤途:实现更加精细的封装
  • 可以访问外围类的实例⽅法
  • ⾮静态内部类
    • 和⼀个外围类实例相绑定
    • 可以访问外围类实例的⽅法
  • 静态内部类
    • 不和外围类实例相绑定
    • 不可以访问外围实例的⽅法
  • 原则:永远使⽤静态内部类,除⾮编译报错

匿名内部类

  • 直接通过new的⽅式创建的⽆名类