【Java】封装在 Java 中是怎样实现的?
包
关于包有两个关键字 package : 声明当前类属于哪个包 和 import : 允许当前类使用其他类或接口时不使用全限定名 , 也就是导包 .
IDEA 的普通项目文件包括 src : 包含源码和资源文件 和 out : 包含编译产物字节码文件 . 在 IDEA 开发环境建包会在 src 源码目录中生成 , 可以用多级目录 如 com.tiktok.java 映射到目录就是 src/com/tiktok/java 路径 和 单级目录 如仅用一个 tiktok , 项目越大越应用多级目录来建包管理项目 . IDEA 会自动生成 package 语句 .
如果导的多个包有同名类 , 在调用该类时要使用类的全限定名 , 否则会编译错误 .
没有显式声明 package 语句的 Java 类属于默认包 , 默认包没有包名 , 类直接位于根目录 , 只能被同样位于默认包的类访问 , 不能被其他非默认包类导包使用 .
* 资源文件的相对路径
相对的是什么 ?
-
当前工作目录 : 程序启动的目录 , IDEA 默认是项目根目录 .
new File("xxx")
-
类路径根目录 : 类加载器加载资源后的根目录 , 即 /target/classes/ 或 out/production/模块名/ .
getClassLoader().getResource("xxx")
-
使用 getResource 寻找 :
-
不以
/
开头 : 相对于当前类所在包 .getClass().getResource("xxx")
-
以
/
开头 : 相对于类路径根目录 .getClass().getResource("/xxx")
-
如果我们在 输入输出流初始化 时 , 直接传入文件名或路径 , 执行会直接访问操作系统的文件系统路径 , 路径是相对于当前工作目录的 .
当前工作目录在 Java 程序运行时是 System.getProperty("user.dir")
. 如果在 IDEA 里运行默认是项目根目录 , 如果打包成 JAR 运行则默认是运行命令的目录 .
类加载器加载资源文件
类加载器加载资源文件时 , 依赖 classpath 路径 ( 如 /out ) , 这个路径的资源来自 src/main/resources 或 src 下的资源 , 编译时会将这些资源复制到输出目录实现运行时访问 .
访问控制
访问控制是 Java 面向对象中封装特性的重要实现 .
访问修饰符
修饰符 | 同类(Class) | 同包(Package) | 子类(不同包) | 其他类(不同包) |
---|---|---|---|---|
private | ✅ 可访问 | ❌ 不可访问 | ❌ 不可访问 | ❌ 不可访问 |
默认(无修饰) | ✅ 可访问 | ✅ 可访问 | ❌ 不可访问 | ❌ 不可访问 |
protected | ✅ 可访问 | ✅ 可访问 | ✅ 可访问(但需通过子类实例) | ❌ 不可访问 |
public | ✅ 可访问 | ✅ 可访问 | ✅ 可访问 | ✅ 可访问 |
跨包子类只能通过自己实例或其子类实例访问父类 protected 修饰的成员 , 跨包子类中的父类实例不能访问这些成员 .
非内部类只能被 public 修饰 , 接口同理 . 内部类和内部接口可以使用其他修饰符修饰 .
* 区分默认方法
访问修饰符中没有 default , Java 8 加入的默认方法 default 关键字是声明修饰符 , 用于接口 , 实现有默认方法的接口的实现类可以选择重写该默认方法 , 也可以选择使用默认方法的方法体默认实现 , 不强制重写 .
* 默认方法 & 钩子方法
接口的默认方法提供默认实现 , 接口不再是方法签名的集合 , 实现类可以不用实现这个方法 , 这样设计便于扩展接口功能 .
钩子方法是父类设计的留白步骤 , 子类可以根据需求插入重写的自定义代码 , 影响执行流程 .
方面 | 默认方法(Default Method) | 钩子方法(Hook Method) |
---|---|---|
定义 | Java 8 引入的接口中带有默认实现的方法,使用 default 关键字声明 | 父类(通常是抽象类)提供的可被子类覆盖的方法,允许子类在执行流程中插入额外行为 |
出现位置 | 出现在接口中 | 出现在类(通常是抽象类)中 |
目的 | 给接口增加新的方法,同时保持向后兼容;避免接口改动导致实现类全部修改 | 提供一个“扩展点”,让子类可以选择性地修改或增强父类行为 |
调用方式 | 通过接口引用调用,或者通过实现类调用 | 通过父类方法调用,子类重写实现 |
实现机制 | 方法体在接口中直接实现 | 抽象类中预定义流程,钩子方法可空实现或默认实现 |
典型应用 | 为接口添加新的功能时不破坏已有实现 | 设计模板方法模式(Template Method Pattern)中的可扩展点 |
是否必须实现 | 不是,接口实现类可以直接使用默认实现 | 不是,子类可以选择重写或不重写 |
Getter/Setter
核心逻辑就是将类字段设置为私有 private , 对外提供 get 和 set 的查询和修改访问接口 , 控制字段读写权限 . 便于添加校验逻辑和额外处理 ( 如 Person 类的年龄 age 不应小于 0 ) , 也可以在 set 方法添加日志打印 , 追踪对象属性的修改情况 , 帮助开发者检查项目运行状态和调试问题 .
JavaBean
细则编号 | 说明 |
---|---|
1 | 类必须实现 无参构造器(默认构造器或显式无参构造器) |
2 | 属性(字段)应为 私有(private),保证封装 |
3 | 对属性的访问通过 getter 和 setter 方法,遵循命名规范 |
4 | getter 方法命名格式:public Type getPropertyName() ,针对布尔类型,也可用 isPropertyName() |
5 | setter 方法命名格式:public void setPropertyName(Type value) |
6 | getter 方法返回属性值,setter 方法用于设置属性值 |
7 | 实现 Serializable 接口,支持对象序列化(可选但推荐) |
8 | 不建议定义 public 的实例变量,避免直接访问 |
9 | 应遵循 Java 命名规范,类名通常是大驼峰(PascalCase),属性名小驼峰(camelCase) |