完成目标:
学习java下半段课程
知识点:
1.多态转型
知识点 |
核心内容 |
重点 |
多态转型 |
向上转型(父类引用指向子类对象) 与向下转型(强制类型转换)的机制与区别 |
向上转型自动完成,向下转型需显式强转 |
向上转型 |
类似double b = 1的小类型自动提升为大类型 |
多态调用时无法使用子类特有方法 |
向下转型 |
通过强制转换(如 Dog dog = (Dog) animal)恢复子类类型以调用特有功能 |
类型不匹配会抛出ClassCastException |
转型应用场景 |
需调用子类特有功能时(如dog.lookDoor())必须向下转型 |
转型前建议用instanceof检查类型安全性 |
2.多态实例
定义笔记本类,具备开机,关机和使用USB设备的功能。具体是什么USB设备,笔记本并不关心,只要符合USB规格的设备都可以。鼠标和键盘要想能在电脑上使用,那么鼠标和键盘也必须遵守USB规范,不然鼠标和键盘的生产出来无法使用;
进行描述笔记本类,实现笔记本使用USB鼠标、USB键盘
- USB接口,包含开启功能、关闭功能
- 笔记本类,包含运行功能、关机功能、使用USB设备功能
- 鼠标类,要符合USB接口
- 键盘类,要符合USB接口
public interface USB {
public abstract void open();
public abstract void close();
}
public class Mouse implements USB{
@Override
public void open() {
System.out.println("鼠标开启");
}
@Override
public void close() {
System.out.println("鼠标关闭");
}
//特有方法
public void click(){
System.out.println("点我");
}
}
public class KeyBoard implements USB{
@Override
public void open() {
System.out.println("键盘开启");
}
@Override
public void close() {
System.out.println("键盘关闭");
}
//特有功能
public void input(){
System.out.println("敲我");
}
}
public class NoteBook {
//开机
public void start(){
System.out.println("开机");
}
//使用USB
/*
USB usb = mouse 多态
USB usb = keyBoard 多态
*/
public void useUSB(USB usb){
if (usb instanceof Mouse){
Mouse mouse = (Mouse) usb;
mouse.open();
mouse.click();
mouse.close();
}else{
KeyBoard keyBoard = (KeyBoard) usb;
keyBoard.open();
keyBoard.input();
keyBoard.close();
}
//usb.open();
//usb.close();
}
//关机
public void stop(){
System.out.println("关机");
}
}
public class Test01 {
public static void main(String[] args) {
NoteBook noteBook = new NoteBook();
Mouse mouse = new Mouse();
noteBook.start();
noteBook.useUSB(mouse);
noteBook.stop();
System.out.println("===========");
KeyBoard keyBoard = new KeyBoard();
noteBook.start();
noteBook.useUSB(keyBoard);
noteBook.stop();
}
}
知识点 |
核心内容 |
重点 |
USB接口设计 |
定义抽象接口包含open()和close()方法,要求设备类(鼠标/键盘)必须实现 |
接口与实现类的多态调用关系 |
笔记本类功能 |
包含开机、关机、使用USB设备方法(useUSB),通过多态调用不同设备的接口方法 |
useUSB方法参数类型为接口,需理解多态的实际应用 |
设备类实现 |
鼠标类(Mouse)和键盘类(Keyboard)实现USB接口,并重写open/close方法 |
特有方法(如click()、input())需通过向下转型调用 |
多态与类型判断 |
在useUSB中通过instanceof判断设备类型,安全调用特有功能 |
避免直接强转导致的类型转换异常 |
案例流程 |
1. 开机 → 2. 插入设备(触发接口方法) → 3. 调用特有功能 → 4. 关机 |
执行顺序与多态调用的联动逻辑 |
3.权限修饰符
知识点 |
核心内容 |
重点 |
权限修饰符 |
Java中四种访问权限:public(公共)、protected(受保护)、default(默认)、private(私有) |
default不能显式声明,仅在接口中隐式使用 |
同类访问 |
四种权限修饰的成员在同类中均可访问 |
无特殊限制 |
同包不同类 |
public/protected/default可访问,private不可访问 |
protected与default易混淆(同包时行为相同) |
不同包子父类 |
public/protected可访问,default/private不可访问 |
protected跨包需继承关系 |
不同包非子父类 |
仅public可访问,其余均不可 |
实际开发中优先用public和private |
开发实践 |
属性用private(封装)、方法用public、构造方法用public |
private构造方法会阻止实例化 |
4.final
知识点 |
核心内容 |
重点 |
final修饰类 |
使类不能被继承(最终类) |
public final class 类名 语法格式 |
final修饰方法 |
使方法不能被重写 |
与abstract关键字冲突(不能同时使用) |
final修饰局部变量 |
变量成为常量(不可二次赋值) |
声明时可以不初始化(但首次赋值后不可更改) |
final修饰对象 |
对象引用地址不可变(但属性值可修改) |
setter方法仍可修改对象属性 |
final修饰成员变量 |
必须显式初始化且不可二次赋值 |
会导致有参构造和setter方法失效 |
final关键字的本质 |
表示"最终的"、"不可改变的"特性 |
不同修饰对象的不可变性表现差异(类/方法/变量) |
5.代码块
知识点 |
核心内容 |
重点 |
构造代码块 |
格式:{ }内直接写代码; 执行特点:优先于构造方法执行,每次创建对象时都会执行 |
与构造方法的执行顺序关系 |
静态代码块 |
格式:static { }; 执行特点:优先于构造代码块和构造方法,且仅执行一次 |
与构造代码块的执行顺序及次数差异 |
静态代码块应用场景 |
JDBC连接数据库的四大参数初始化: 1. 注册驱动; 2. 数据库地址; 3. 用户名; 4. 密码; (需最早初始化且仅一次) |
为何不重复初始化?静态代码块的不可替代性 |
代码块对比 |
静态代码块 vs 构造代码块: - 执行时机:静态>构造>构造方法; - 执行次数:静态(1次) vs 构造(N次) |
实际开发中优先使用静态代码块 |
6.内部类
知识点 |
核心内容 |
重点 |
内部类定义 |
类内部定义的类,用于描述外部类中需要完整结构(属性和行为)的成员 |
区分内部类与嵌套类概念 |
使用场景 |
当外部类某成员需独立属性和行为,且仅服务于外部类时(如人类与心脏) |
理解“只为外部事物提供服务”的核心逻辑 |
JAVA语法规则 |
类A包含类B时,A为外部类,B为内部类(class A { class B {...} }) |
静态/非静态成员内部类的语法差异 |
内部类分类 |
成员内部类(静态/非静态)、局部内部类、匿名内部类(重点) |
匿名内部类的实际应用场景(如事件监听) |
案例 |
人的心脏作为内部类,需独立描述跳动频率、供血功能等属性和行为 |
类比其他生物结构(如汽车与发动机) |
7.成员内部类
知识点 |
核心内容 |
重点 |
静态成员内部类 |
定义时添加static关键字(如static class B),可包含属性/方法/构造器,支持final或abstract修饰(不可同时使用) |
静态内部类不能调用外部类非静态成员;权限修饰符使用规则与外部类相同 |
非静态成员内部类 |
定义时不加static,其余结构与静态内部类类似 |
调用方式需通过外部类实例 (new Outer().new Inner()) |
调用方式对比 |
静态内部类:Outer.Inner obj = new Outer.Inner(); 非静态内部类:Outer.Inner obj = new Outer().new Inner() |
语法差异:非静态需先实例化外部类 |
修饰符限制 |
final修饰后不可继承;abstract修饰后不可实例化 |
注意final与abstract互斥性 |
实际应用示例 |
Person.Heart静态内部类模拟心脏跳动方法(jump()) |
通过Person.Heart heart = new Person.Heart()调用 |
8.局部内部类
知识点 |
核心内容 |
重点 |
局部内部类 |
定义在方法、代码块或构造器中的内部类,作用域与局部变量一致 |
外部类无法直接实例化局部内部类,需通过封装方法间接调用 |
匿名内部类 |
局部内部类的特殊形式,无显式类名,直接通过接口/父类实例化 |
语法糖特性,需理解new 接口(){...}的底层实现逻辑 |
调用限制 |
局部内部类仅能在定义它的方法/块内实例化,外部需通过封装方法(如eat())间接调用 |
成员内部类 vs 局部内部类的实例化权限差异 |
语法示例 |
class Heart { void jump() {...} } 在eat()方法内定义, 通过new Heart().jump()调用 |
方法内定义的类不能使用static修饰 |
9.局部内部类实际操作
知识点 |
核心内容 |
重点 |
局部内部类的实际操作 |
实际操作复杂,需通过接口、抽象类作为方法参数传递和返回值返回来理解 |
局部内部类的实际操作方式 |
接口作为方法参数传递 |
定义接口类型,实现类实现接口并重写方法,方法参数传递接口类型,实际传递的是实现类对象 |
接口不能直接实例化,需传递实现类对象 |
接口作为方法返回值 |
方法返回值类型为接口类型,实际返回的是接口的实现类对象 |
返回值类型与实际返回对象类型的区别 |
抽象类作为方法参数传递 |
抽象类不能实例化,方法参数传递抽象类类型,实际传递的是其子类对象 |
抽象类与子类对象的传递关系 |
抽象类作为方法返回值 |
方法返回值类型为抽象类类型,实际返回的是其子类对象 |
抽象类作为返回值类型的理解 |
普通类作为方法参数和返回值 |
普通类作为方法参数传递的是对象,作为方法返回值返回的也是对象 |
普通类对象的传递与返回 |
接口作为方法参数传递,实际传递的是实现类对象 ;
接口作为方法返回值,实际返回的是接口的实现类对象:
public interface USB {
public abstract void open();
}
public class Mouse implements USB{
@Override
public void open() {
System.out.println("鼠标打开");
}
}
public class Test01 {
public static void main(String[] args) {
Mouse mouse = new Mouse();
method(mouse);
System.out.println("================");
USB usb = method01();//USB usb = new Mouse();
usb.open();
}
/*
接口作为方法参数,传递实参时,传递的是实现类对象
*/
public static void method(USB usb){//USB usb = mouse -> 多态
usb.open();
}
/*
接口作为返回值类型返回,实际返回的是实现类对象
*/
public static USB method01(){
//Mouse mouse = new Mouse();
//return mouse;
return new Mouse();
}
}
抽象类作为方法参数传递,实际传递的是其子类对象;
抽象类作为方法返回值,实际返回的是其子类对象:
public abstract class Animal {
public abstract void eat();
}
public class Dog extends Animal{
@Override
public void eat() {
System.out.println("狗啃骨头");
}
}
public class Test02 {
public static void main(String[] args) {
Dog dog = new Dog();
method01(dog);
System.out.println("=================");
Animal animal = method02();//Animal animal = new Dog()
animal.eat();
}
public static void method01(Animal animal){//Animal animal = dog
animal.eat();
}
public static Animal method02(){
return new Dog();
}
}
普通类作为方法参数传递的是对象,作为方法返回值返回的也是对象
public class Person {
public void eat(){
System.out.println("人要干饭");
}
}
public class Test03 {
public static void main(String[] args) {
Person person = new Person();
method01(person);
System.out.println("==================");
Person person1 = method02();//Person person1 = new Person()
person1.eat();
}
public static void method01(Person person){
person.eat();
}
public static Person method02(){
return new Person();
}
}
10.匿名内部类
知识点 |
核心内容 |
重点 |
匿名内部类定义 |
没有显示声明类名的内部类,编译时会隐式生成对应class文件 |
与局部内部类的命名区别 |
使用场景 |
单次调用接口方法时替代传统四步实现方式(创建实现类→重写方法→实例化→调用) |
与传统实现方式的步骤对比 |
语法格式 |
new 接口/抽象类 ( ) { 重写方法 }.重写的方法(); 代表实现类/子类对象 |
匿名对象与有名对象的调用区别 |
编译机制 |
每个new操作会在编译时生成独立class文件(示例中生成2个匿名类文件) |
类文件命名规则与生成逻辑 |
典型应用 |
USB接口案例:通过匿名内部类同时完成实现和实例化 |
open()/close()方法的多重调用限制 |
优劣对比 |
优势:简化单次调用代码;劣势:复杂逻辑可读性差 |
与Lambda表达式的适用场景差异 |
11.匿名内部类在开发中的使用
知识点 |
核心内容 |
重点 |
匿名内部类作为参数传递 |
通过method01(USB usb)方法演示,直接传入new USB(){...}匿名内部类对象,替代传统实现类实例化 |
匿名内部类语法格式(new 接口/抽象类(){...})与常规实现类的区别 |
匿名内部类作为返回值 |
在method01()中直接返回new USB(){...}对象,调用时通过USB usb = method01(); usb.open();执行 |
返回值类型需匹配接口,匿名内部类对象需完整实现抽象方法 |
执行流程解析 |
1. 调用方法 → 2. 传递/返回匿名内部类对象(本质为实现类实例) → 3. 调用重写方法(如open()) |
对象生命周期:匿名内部类对象仅在调用时创建,无显式类定义 |
匿名内部类作为参数传递
匿名内部类作为返回值
12.API文档
知识点 |
核心内容 |
重点 |
API定义 |
Application Programming Interface(应用编程接口),包含预定义的类、接口及其成员方法 |
需区分API与API文档的概念差异 |
API文档作用 |
程序员离线查询工具,支持按类/包检索方法说明 (如Scanner类的方法参数与返回值) |
必须掌握类名/包名才能有效查询,否则需依赖网络搜索 |
API文档结构 |
包含: 1. 类继承体系(如Scanner→Object); 2. 实现接口(如Iterator); 3. 方法详情(返回值类型/参数/功能说明) |
重点查看方法签名(如void close())和功能描述字段 |
文档使用技巧 |
1. 通过索引搜索类名(不区分大小写); 2. 任务栏快捷访问配置(右键→工具栏→新建工具栏) |
高频易错:直接搜索方法名无效,需通过类名定位 |
离线查询优势 |
无网络环境下仍可快速检索已知类的方法细节(如Scanner.nextInt()的异常处理) |
对比百度搜索,精准性更高但前提条件严格 |
13.异常
知识点 |
核心内容 |
重点 |
异常概念 |
代码运行中出现的不正常现象,分为错误(Error)和异常(Exception) |
异常≠语法错误,异常是运行时问题而非语法问题 |
异常体系结构 |
Throwable(可抛的)为顶级父类,包含Error和Exception两个子类 |
Error代表重大错误(如内存溢出),Exception代表可处理问题 |
异常分类 |
编译时期异常(检查型异常) vs 运行时期异常(非检查型异常) |
编译异常:代码编译时报错;运行异常:运行时才报错 |
编译时期异常 |
Exception类及其子类(除RuntimeException分支) |
典型特征:调用方法时底层抛出,如SimpleDateFormat的parse() |
运行时期异常 |
RuntimeException及其子类(如数组越界异常) |
典型特征:编译不报错但运行时报错 |
异常处理机制 |
异常未被处理时会自动向上抛出,最终由JVM默认处理 |
处理流程:打印异常堆栈 → 终止程序执行 |
典型错误示例 |
递归调用导致栈溢出(StackOverflowError) |
Error不可恢复,必须重构代码 |
典型异常示例 |
数组越界(ArrayIndexOutOfBoundsException) vs 日期解析异常(ParseException) |
运行异常不强制处理,编译异常必须处理 |