知识点 |
核心内容 |
重点 |
抽象类实例化限制 |
抽象类不能直接实例化对象,只能创建非抽象子类的对象 |
尝试实例化抽象类会触发编译错误 |
抽象方法与抽象类关系 |
抽象类不一定包含抽象方法,但含抽象方法的类必须是抽象类 |
定义顺序影响类声明(先有抽象方法需声明抽象类) |
子类重写要求 |
子类必须重写父类所有抽象方法,否则需声明为抽象类 |
漏写重写方法等价于隐含继承父类抽象方法 |
抽象类成员结构 |
可包含成员变量/构造方法/普通方法,与普通类差异仅在于抽象方法 |
构造方法用于子类初始化父类属性(非自身实例化) |
构造方法作用机制 |
抽象类构造方法专用于子类对象初始化时设置父类属性 |
通过super()调用父类构造方法实现属性传递 |
某IT公司有多名员工,按照员工负责的工作不同,进行了部门的划分(研发部、维护部)。
研发部(Developer)根据所需研发的内容不同,又分为 JavaEE工程师 、Android工程师 ;
维护部(Maintainer)根据所需维护的内容不同,又分为 网络维护工程师(Network) 、硬件维护工程师(Hardware) 。
公司的每名员工都有他们自己的员工编号、姓名,并要做它们所负责的工作。
工作内容:
- JavaEE工程师: 员工号为xxx的 xxx员工,正在研发电商网站
- Android工程师:员工号为xxx的 xxx员工,正在研发电商的手机客户端软件
- 网络维护工程师:员工号为xxx的 xxx员工,正在检查网络是否畅通
- 硬件维护工程师:员工号为xxx的 xxx员工,正在修复电脑主板
根据描述,完成员工体系中所有类的定义,并指定类之间的继承关系。进行XX工程师类的对象创建,完成工作方法的调用。
public abstract class Employee {
private int id;
private String name;
public Employee() {
}
public Employee(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public abstract void work();
}
```
public abstract class Developer extends Employee{
}
public class JavaEE extends Developer{
@Override
public void work() {
//System.out.println("员工号为:"+getId()+"的"+getName()+"正在开发网站");
System.out.println("员工号为:"+this.getId()+"的"+this.getName()+"正在开发网站");
}
}
public class Android extends Developer{
@Override
public void work() {
//System.out.println("员工号为:"+getId()+"的"+getName()+"正在开发app");
System.out.println("员工号为:"+this.getId()+"的"+this.getName()+"正在开发app");
}
}
public class Test01 {
public static void main(String[] args) {
JavaEE javaEE = new JavaEE();
javaEE.setId(1);
javaEE.setName("涛哥");
javaEE.work();
System.out.println("===============");
Android android = new Android();
android.setId(2);
android.setName("金莲");
android.work();
}
}
知识点 |
核心内容 |
重点 |
接口定义 |
使用interface关键字定义引用数据类型,是一种标准/规范 |
接口与抽象类的区别; 接口成员默认修饰符规则 |
接口实现 |
通过implements关键字创建实现类; 必须重写所有抽象方法 |
实现类与子类概念区分; 接口不能直接实例化 |
JDK7接口特性 |
仅包含: - public abstract抽象方法; - public static final常量 |
抽象方法修饰符可省略; 常量必须初始化 |
JDK8新增特性 |
支持: - default默认方法(带实现); - static静态方法 |
默认方法冲突解决规则; 静态方法接口专属调用方式 |
多态应用 |
通过接口引用指向实现类对象; Mouse m = new Mouse() |
运行时绑定机制; 类型转换异常风险点 |
生活化案例 |
插座/USB接口类比: - 统一标准; - 强制规范 |
接口设计开闭原则体现; 扩展性vs约束性平衡 |
1.定义接口:
public interface 接口名{}
2.实现:
public class 实现类类名 implements 接口名{}
3.使用:
a.实现类实现接口
b.重写接口中的抽象方法
c.创建实现类对象(接口不能直接new对象)
d.调用重写的方法
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 class Test01 {
public static void main(String[] args) {
Mouse mouse = new Mouse();
mouse.open();
mouse.close();
}
}
知识点 |
核心内容 |
重点 |
默认方法 |
JDK8新增特性,格式为public default 返回值 方法名(),包含方法体实现,可通过实现类对象调用 |
1. 与抽象方法区别:有方法体; 2. 可重写可不重写; 3. 必须通过实现类调用 |
静态方法 |
JDK8新增,格式为public static 返回值 方法名(), 直接通过接口名调用 |
1. 不需要实现类; 2. 调用方式与类静态方法相同 |
应用场景 |
1. 作为临时添加的小功能; 2. 避免因添加抽象方法导致所有实现类报错 |
1. 默认方法:功能扩展; 2. 静态方法:工具类功能 |
语法注意点 |
1. 实现类重写默认方法时不能加default关键字; 2. 静态方法不能被实现类继承或重写 |
1. @Override注解可验证重写; 2. 接口静态方法 vs 类静态方法调用方式 |
知识点 |
核心内容 |
重点 |
接口中的成员变量定义 |
使用public static final修饰成员变量(如int NUM=100),默认隐含该修饰,需手动初始化 |
final变量的不可变性、默认修饰符规则 |
静态成员调用方式 |
通过接口名直接调用静态变量(如USB.NUM) |
接口与类静态成员调用语法的区别 |
开发规范 |
static final修饰的变量名需全大写(如NUM而非num) |
命名习惯与实际语法约束的差异 |
final关键字的特性 |
被修饰变量为常量,禁止二次赋值 |
final与普通变量的初始化要求对比 |
知识点 |
核心内容 |
重点 |
接口特点 |
1. 可以多继承(一个接口继承多个接口); 2. 可以多实现(一个类实现多个接口); 3. 子类可同时继承父类和实现接口 |
接口继承 vs 类继承; 类单继承 vs 接口多继承 |
接口实现注意事项 |
1. 多个接口抽象方法重名时只需重写一次; 2. 多个接口默认方法重名时必须重写 |
抽象方法冲突只需实现一次; 默认方法冲突强制重写 |
接口与抽象类区别 |
相同点: - 都位于继承体系顶端; - 都不能实例化; - 都包含抽象方法; 不同点: - 抽象类可包含成员变量/构造方法; - 接口侧重功能集合 |
设计定位差异: 抽象类→父类扩展; 接口→功能契约 |
命名规范 |
实现类推荐使用Impl后缀(implements缩写) |
开发中通过命名快速识别实现类 |
代码示例 |
interface A extends B,C; class Impl implements A,B; class Sub extends Parent implements A,B |
多继承语法糖写法 |
知识点 |
核心内容 |
重点 |
多态概念 |
面向对象三大特征之一,强调方法重写和父类引用指向子类对象 |
不要从字面理解"一个事物多种形态",要从使用形式理解 |
多态前提条件 |
1. 必须有子父类继承或接口实现关系; 2. 必须有方法重写(无重写则多态无意义) |
成员变量在多态中无意义,重点关注重写方法 |
多态实现方式 |
父类类型 变量名 = new 子类构造器(); 类比基本数据类型转换:double b = 10(大类型接收小类型) |
与常规new对象方式(Dog d = new Dog())的语法区别 |
多态调用限制 |
不能直接调用子类特有功能; 只能调用重写方法和父类定义的方法 |
与继承中new父类对象不能调子类方法的规则一致 |
多态应用示例 |
Animal a = new Dog(); a.eat()调用的是Dog重写方法; Animal a2 = new Cat(); a2.eat()调用Cat重写方法 |
编译看左边,运行看右边的调用机制 |
多态专业术语 |
英文术语:Polymorphic; 代码特征:抽象类/接口+实现类重写 |
需区分抽象类与接口的实现方式差异 |
多态实现:
public abstract class Animal {
public abstract void eat();
}
public class Dog extends Animal{
@Override
public void eat() {
System.out.println("狗啃骨头");
}
//特有方法
public void lookDoor(){
System.out.println("狗会看门");
}
}
public class Cat extends Animal{
@Override
public void eat() {
System.out.println("猫吃鱼");
}
//特有方法
public void catchMouse(){
System.out.println("猫会捉老鼠");
}
}
public class Test01 {
public static void main(String[] args) {
//原始方式
Dog dog = new Dog();
dog.eat();//重写的
dog.lookDoor();//特有的
Cat cat = new Cat();
cat.eat();//重写的
cat.catchMouse();//特有的
System.out.println("==================");
//多态形式new对象
Animal animal = new Dog();//相当于double b = 10
animal.eat();//重写的 animal接收的是dog对象,所以调用的是dog中的eat
// animal.lookDoor(); 多态前提下,不能直接调用子类特有成员
Animal animal1 = new Cat();
animal1.eat();//cat重写的
}
}
知识点 |
核心内容 |
重点 |
多态成员的访问特点 |
成员变量访问看等号左边(编译类型),成员方法调用看new的对象(运行类型) |
成员变量无多态性(输出1000),成员方法有多态性(输出子类重写方法) |
继承口诀应用 |
成员变量:看左边(父类);成员方法:看new谁(子类优先) |
易混淆变量与方法的访问规则差异 |
多态本质 |
主要玩方法重写,不涉及成员变量的多态性 |
实际开发中强调方法重写的优先级 |
知识点 |
核心内容 |
重点 |
多态的定义与形式 |
父类引用指向子类对象(Animal a = new Dog()),通过父类类型调用子类重写方法 |
多态与原始方式(Dog d = new Dog())的语法区别 |
多态的优缺点对比 |
优点:扩展性强(父类类型可接收任意子类对象); 缺点:无法直接调用子类特有成员 |
原始方式 vs 多态方式的调用权限差异(重写/继承/特有方法) |
扩展性案例 |
方法形参定义为父类类型(void method(Animal a)),可传递不同子类对象(Dog/Cat),调用各自重写方法 |
原始方式需为每个子类单独定义方法(method(Dog d), method(Cat c)) |
多态的应用场景 |
框架开发、对象传递时优先使用多态,核心价值是统一调用重写方法,而非调用子类特有功能 |
易混淆点:多态并非为调用特有功能设计 |
类型转换与接收范围 |
类比double b = 10(大类型接收小类型),多态中父类类型可接收所有子类对象 |
类型不匹配时的编译错误(如Dog d = new Cat()) |
在开发实践中:多态是许多设计模式的基础;多数Java框架底层都使用多态机制