当前位置: 首页 > news >正文

【从零开始java学习|第十七篇】面向对象进阶

目录

一、封装

二、包(Package):类的 “组织与管理工具”

1. 包的核心作用

2. 包的定义与命名规范

(1)定义语法

(2)命名规范(强制遵循,面试常考)

3. 包的导入(import):使用其他包的类

(1)三种导入方式

(2)示例:导入与使用

(3)注意:默认导入的包

4. 包的访问权限(与 default 修饰符联动)

三、final 关键字:“不可修改” 的约束工具

1. final 修饰类:类不能被继承

2. final 修饰方法:方法不能被重写

3. final 修饰变量:变量不能被重新赋值

(1)final 修饰局部变量

(2)final 修饰成员变量

(3)final 修饰引用变量(面试高频)

(4)static final:静态常量(面试重点)

4. final 的核心面试考点

四、权限修饰符:控制 “访问范围” 的工具

1. 4 种权限修饰符的访问范围(面试必记)

关键说明:

2. 权限修饰符的典型应用场景

(1)private:封装成员变量

(2)protected:子类继承访问

(3)public:暴露公共接口

(4)default:同包内复用

3. 权限修饰符的面试高频问题

五、代码块:“初始化逻辑” 的载体

1. 静态代码块(Static Block)

(1)定义与执行时机

(2)核心作用

(3)示例:

2. 实例代码块(Instance Block)

(1)定义与执行时机

(2)核心作用

3. 局部代码块(Local Block)

(1)定义与执行时机

4. 代码块的执行顺序

六、总结与面试核心串联


一、封装

封装 = 把数据藏起来,只留安全门
将类的属性私有化private),外界只能通过公开方法get/set 或其他业务方法)间接访问,从而在方法里加校验、隐藏实现细节、降低耦合。

生活例子:ATM 卡

  1. 你的余额是 private —— 外部不能直接改。

  2. 存钱/取钱走 public 方法 deposit() / withdraw()

    • 存钱:负金额拒绝。

    • 取钱:余额不足拒绝;大额还要短信验证。

  3. 结果:

    • 钱不会被“隔空”乱改;

    • 所有业务规则集中在一个类里,外部只关心“能存能取”,不用管内部怎么算利息、怎么记日志。

二、包(Package):类的 “组织与管理工具”

在 Java 中,包是用于组织类和接口的目录结构,核心作用是解决 “类名冲突” 和 “代码分类管理” 问题,是大型项目中代码结构化的基础。

1. 包的核心作用

  • 避免类名冲突:不同包中可存在同名类(如com.example.Usercom.test.User),通过 “包名 + 类名” 的全限定名区分;
  • 分类管理代码:按功能 / 模块划分包(如controller存接口类、service存业务逻辑类、dao存数据访问类),便于维护;
  • 控制访问权限:配合default权限修饰符,实现 “同包可见,跨包不可见” 的访问控制。

2. 包的定义与命名规范

(1)定义语法

.java文件的第一行声明包,格式:

package 包名; // 必须在文件最顶部,且只能有一个package语句// 示例:声明类属于com.example.demo包
package com.example.demo;public class User { ... }
(2)命名规范(强制遵循,面试常考)
  • 采用 “域名反转” 格式(全小写,避免与类名冲突),如公司项目常用com.公司名.项目名.模块名
  • 示例:
    • 阿里巴巴电商项目:com.alibaba.ecommerce.order(订单模块);
    • 个人学习项目:com.study.demo.util(工具类模块)。

3. 包的导入(import):使用其他包的类

当需要使用非当前包的类时,需通过import语句导入,避免每次写全限定名(如com.example.demo.User)。

(1)三种导入方式
导入方式语法示例说明
导入单个类import com.example.demo.User;仅导入指定包下的单个类,推荐优先使用
导入整个包的类import com.example.demo.*;导入指定包下的所有类(不包含子包)
导入静态成员import static java.lang.Math.PI;导入类的静态变量 / 方法(无需类名调用)
(2)示例:导入与使用
// 导入java.util包下的ArrayList类
import java.util.ArrayList;
// 导入java.lang.Math的静态成员PI
import static java.lang.Math.PI;public class PackageDemo {public static void main(String[] args) {// 使用导入的ArrayList(无需写全限定名)ArrayList<String> list = new ArrayList<>();// 使用导入的静态常量PI(无需写Math.PI)System.out.println("圆的周长:" + 2 * PI * 5); }
}
(3)注意:默认导入的包

Java 会自动导入java.lang包(如StringMathSystem),无需手动写import,例如:

// 无需import java.lang.String,直接使用
String str = "Hello";
// 无需import java.lang.System,直接使用
System.out.println(str);

4. 包的访问权限(与 default 修饰符联动)

包的访问控制依赖权限修饰符(后续详解),其中default(默认权限,无修饰符)的规则是:

  • default修饰的类、成员变量、方法,仅同包内的类可访问,跨包不可访问

示例:

// 包1:com.example.a
package com.example.a;// default类(无修饰符):仅com.example.a包内可访问
class DefaultClass {// default方法:仅同包可访问void defaultMethod() {System.out.println("同包可见");}
}// 包2:com.example.b(跨包)
package com.example.b;
import com.example.a.DefaultClass; // 编译报错:DefaultClass是default类,跨包不可见

三、final 关键字:“不可修改” 的约束工具

final是 Java 中用于 “限制修改” 的关键字,可修饰类、方法、变量,核心作用是 “锁定” 目标,避免被篡改,是封装和安全性的重要支撑。

1. final 修饰类:类不能被继承

  • 语法final class 类名 { ... }
  • 作用:禁止该类有子类(即 “最终类”),确保类的逻辑不被修改;
  • 典型场景:Java 内置的StringInteger等类都是final类,避免被继承后破坏不可变性;
  • 注意:final 类中的方法默认是 final 方法(无需显式声明),但成员变量可非 final。

示例:

// final类:不能被继承
final class FinalClass {public void show() {System.out.println("final类的方法");}
}// class SubClass extends FinalClass { ... } // 编译报错:无法继承final类

2. final 修饰方法:方法不能被重写

  • 语法public final void 方法名() { ... }
  • 作用:禁止子类重写该方法,确保父类方法的逻辑不被篡改;
  • 典型场景:父类中核心逻辑的方法(如计算规则、安全校验),不允许子类修改。

示例:

class Parent {// final方法:子类不能重写public final void finalMethod() {System.out.println("父类的final方法");}
}class Child extends Parent {// @Override // 编译报错:无法重写final方法// public void finalMethod() { ... }
}

3. final 修饰变量:变量不能被重新赋值

final 修饰变量时,变量成为 “常量”,只能赋值一次,赋值后不可修改。根据变量类型(局部变量、成员变量),初始化时机不同。

(1)final 修饰局部变量
  • 必须在使用前初始化(可显式赋值或通过表达式赋值),赋值后不可修改;
  • 示例:
    public void testLocalFinal() {// 显式初始化final int num1 = 10;// num1 = 20; // 编译报错:final变量不能重新赋值// 先声明,后初始化(使用前必须赋值)final int num2;num2 = 20; // 合法// num2 = 30; // 编译报错
    }
    
(2)final 修饰成员变量
  • 必须在对象创建完成前初始化,有三种方式:
    1. 显式初始化(声明时赋值);
    2. 构造器初始化(每个构造器都必须赋值);
    3. 静态代码块初始化(仅静态 final 变量可用);
  • 示例:
    class FinalVarDemo {// 1. 显式初始化final String var1 = "显式初始化";// 2. 构造器初始化(声明时不赋值)final String var2;public FinalVarDemo() {var2 = "构造器初始化"; // 必须赋值,否则编译报错}// 3. 静态final变量:静态代码块初始化static final String STATIC_VAR;static {STATIC_VAR = "静态代码块初始化";}
    }
    
(3)final 修饰引用变量(面试高频)
  • final 修饰引用变量时,引用地址不可修改,但引用指向的对象内容可修改;
  • 示例:
    public class FinalRefDemo {public static void main(String[] args) {// final引用变量:地址不可变final ArrayList<String> list = new ArrayList<>();// 合法:对象内容可修改list.add("a");list.add("b");// 非法:引用地址不可修改// list = new ArrayList<>(); // 编译报错}
    }
    
(4)static final:静态常量(面试重点)
  • 同时用staticfinal修饰的变量,称为 “静态常量”,具备两个特性:
    1. static:属于类,仅初始化一次,内存中唯一;
    2. final:值不可修改;
  • 命名规范:全大写,单词间用下划线分隔(如PIMAX_VALUE);
  • 典型场景:Java 内置的Math.PIInteger.MAX_VALUE

4. final 的核心面试考点

  • final 类能否有子类? 不能,final 类禁止继承;
  • final 方法能否被重载? 可以!重载是同一类中同名不同参数,与 final 无关(final 仅禁止重写);
  • final 引用变量能否修改对象内容? 可以,final 仅锁定引用地址,不锁定对象内容;
  • static final 变量和 final 变量的区别? 静态常量属于类(全局唯一),final 变量属于对象(每个对象一份,值不可变)。

四、权限修饰符:控制 “访问范围” 的工具

Java 提供 4 种权限修饰符,用于控制类、成员变量、成员方法的访问范围,是封装特性的核心实现(隐藏内部细节,暴露必要接口)。

1. 4 种权限修饰符的访问范围(面试必记)

按访问范围从大到小排序:public > protected > default(默认) > private,具体范围如下表:

权限修饰符本类可见同包其他类可见不同包子类可见全局所有类可见可修饰的目标
public类、成员变量、成员方法
protected成员变量、成员方法(不能修饰类)
default类、成员变量、成员方法(无修饰符)
private成员变量、成员方法(不能修饰类)
关键说明:
  • default:无任何修饰符,仅同包可见;
  • protected:跨包子类可见,但需通过 “子类对象” 或 “子类内部” 访问(不能通过 “父类对象” 跨包访问);
  • 类的修饰限制:仅publicdefault可修饰类(外部类),protectedprivate不能修饰外部类(可修饰内部类)。

2. 权限修饰符的典型应用场景

(1)private:封装成员变量
  • private修饰成员变量,禁止外部直接访问,通过publicgetter/setter方法暴露访问接口,实现数据安全;
  • 示例(JavaBean 的封装):
    public class User {// private成员变量:外部不可直接访问private String name;// public getter:外部获取namepublic String getName() {return name;}// public setter:外部修改name,可加校验public void setName(String name) {if (name != null && !name.isEmpty()) {this.name = name;}}
    }
    
(2)protected:子类继承访问
  • protected修饰父类的成员,允许不同包的子类访问,同时禁止非子类的全局访问;
  • 示例:
    // 包1:com.example.parent
    package com.example.parent;
    public class Parent {// protected方法:不同包子类可访问protected void protectedMethod() {System.out.println("父类的protected方法");}
    }// 包2:com.example.child(不同包的子类)
    package com.example.child;
    import com.example.parent.Parent;
    public class Child extends Parent {public void test() {// 合法:子类内部访问父类的protected方法protectedMethod();}
    }
    
(3)public:暴露公共接口
  • public修饰类或方法,作为对外的 “公共接口”(如工具类的静态方法、服务类的核心方法);
  • 示例:java.util.Arrayssort()方法(public static void sort (int [] a)),全局可调用。
(4)default:同包内复用
  • 用 default 修饰类或成员,仅允许同包内的类访问,适合模块内部的代码复用(避免外部依赖);
  • 示例:项目内部的工具类(如com.example.util.InternalUtil),仅同包的业务类使用。

3. 权限修饰符的面试高频问题

  • private 成员能否被子类继承? 不能!private 成员仅父类内部可见,子类无法继承;
  • protected 成员在不同包的非子类中能否访问? 不能!protected 仅允许同包或不同包的子类访问;
  • 一个.java 文件中能否有多个 public 类? 不能!一个.java 文件只能有一个 public 类,且类名必须与文件名一致;
  • 为什么 JavaBean 的成员变量用 private,而 getter/setter 用 public? 用 private 封装数据,避免外部直接修改;用 public 暴露安全的访问接口,可在 setter 中加数据校验(如年龄范围、非空判断)。

五、代码块:“初始化逻辑” 的载体

代码块是 Java 中用于 “集中执行初始化逻辑” 的代码片段,按定义位置和执行时机分为静态代码块、实例代码块、局部代码块,核心作用是简化初始化操作。

1. 静态代码块(Static Block)

(1)定义与执行时机
  • 语法:在类中,用static修饰的代码块:
    static {// 初始化逻辑(仅执行一次)
    }
    
  • 执行时机类加载时执行(早于对象创建),且仅执行一次(无论创建多少对象,静态代码块只运行一次);
  • 执行顺序:多个静态代码块按定义顺序执行。
(2)核心作用
  • 初始化静态变量(尤其是复杂初始化,如读取配置文件、加载驱动);
  • 执行类级别的预处理操作(如注册监听器、初始化工具类)。
(3)示例:
public class StaticBlockDemo {// 静态变量static String config;// 静态代码块1:初始化configstatic {System.out.println("静态代码块1执行");config = "数据库连接地址:jdbc:mysql://localhost:3306/test";}// 静态代码块2:按定义顺序执行static {System.out.println("静态代码块2执行");}public static void main(String[] args) {// 类加载时已执行静态代码块System.out.println(config);// 输出顺序:静态代码块1执行 → 静态代码块2执行 → 数据库连接地址:...}
}

2. 实例代码块(Instance Block)

(1)定义与执行时机
  • 语法:在类中,无static修饰的代码块:
    {// 初始化逻辑(每次创建对象都执行)
    }
    
  • 执行时机对象创建时执行(在构造方法之前执行),每次创建对象都会执行一次
  • 执行顺序:多个实例代码块按定义顺序执行,执行完所有实例代码块后,再执行构造方法。
(2)核心作用
  • 初始化实例变量(多个构造方法共享的初始化逻辑,避免重复代码);
  • 示例:
    public class InstanceBlockDemo {int num;// 实例代码块:初始化num{System.out.println("实例代码块执行");num = 10; // 所有构造方法创建的对象,num初始值都是10}// 构造方法1public InstanceBlockDemo() {System.out.println("无参构造执行,num=" + num);}// 构造方法2public InstanceBlockDemo(int num) {this.num = num; // 覆盖实例代码块的初始化值System.out.println("有参构造执行,num=" + num);}public static void main(String[] args) {new InstanceBlockDemo(); // 输出:实例代码块执行 → 无参构造执行,num=10new InstanceBlockDemo(20); // 输出:实例代码块执行 → 有参构造执行,num=20}
    }
    

3. 局部代码块(Local Block)

(1)定义与执行时机
  • 语法:在方法内代码块内的代码片段,用{}包裹:
    public void method() {// 局部代码块{int localVar = 10;System.out.println(localVar);}// System.out.println(localVar); // 编译报错:localVar作用域已结束
    }
    
  • 执行时机:随方法调用而执行,执行完后局部变量立即释放;
  • 核心作用控制局部变量的作用域(缩小变量生命周期,节省内存)。

4. 代码块的执行顺序

当一个类包含静态代码块、实例代码块、构造方法时,执行顺序为:
静态代码块(类加载时执行,仅一次) → 实例代码块(对象创建时执行,每次创建都执行) → 构造方法(实例代码块之后执行)

示例验证:

public class BlockOrderDemo {// 静态代码块static {System.out.println("1. 静态代码块");}// 实例代码块{System.out.println("2. 实例代码块");}// 构造方法public BlockOrderDemo() {System.out.println("3. 构造方法");}public static void main(String[] args) {System.out.println("创建第一个对象:");new BlockOrderDemo(); // 输出:1. 静态代码块 → 2. 实例代码块 → 3. 构造方法System.out.println("\n创建第二个对象:");new BlockOrderDemo(); // 输出:2. 实例代码块 → 3. 构造方法(静态代码块已执行过)}
}

六、总结与面试核心串联

  1. 包与权限修饰符的联动:包通过目录结构划分代码,权限修饰符通过default/protected控制包内 / 跨包访问,共同实现代码的模块化和安全性;
  2. final 与封装的联动:final 修饰类 / 方法 / 变量,锁定核心逻辑和数据,配合 private 封装,进一步增强代码的不可篡改性;
  3. 代码块与初始化的关系:静态代码块初始化类级资源,实例代码块初始化对象级资源,简化多构造方法的重复初始化逻辑;
  4. 常见问题:
    • “一个类的初始化顺序是怎样的?”:静态代码块 → 实例代码块 → 构造方法;
    • “final、static final、static 的区别?”:final 值不可变,static 属于类,static final 是类级常量(值不可变 + 全局唯一);
    • “protected 权限在不同包的非子类中能否访问?”:不能,protected 仅允许同包或不同包的子类访问。

如果我的内容对你有帮助,请点赞,评论,收藏。接下来我将继续更新相关内容!


文章转载自:

http://wxqcvLXP.dpqqg.cn
http://v5zVskGV.dpqqg.cn
http://G6Aq7Fy6.dpqqg.cn
http://EBFQ200L.dpqqg.cn
http://RbB2LC9q.dpqqg.cn
http://Y6UbXKpP.dpqqg.cn
http://BygiisxB.dpqqg.cn
http://8UXSnUDH.dpqqg.cn
http://Kw2gwyNq.dpqqg.cn
http://7kpnoZKr.dpqqg.cn
http://qD0dDTmJ.dpqqg.cn
http://vnZcqEau.dpqqg.cn
http://UsS7ygFo.dpqqg.cn
http://SpBSAg9m.dpqqg.cn
http://7Y9MwJRO.dpqqg.cn
http://YFFVYcty.dpqqg.cn
http://XyA30k4I.dpqqg.cn
http://nEccJwSe.dpqqg.cn
http://ovytdj5y.dpqqg.cn
http://kKFluojl.dpqqg.cn
http://OakQ9VpD.dpqqg.cn
http://Yhgoc6iA.dpqqg.cn
http://mHYR2f6O.dpqqg.cn
http://sBQjRpXR.dpqqg.cn
http://73krReT2.dpqqg.cn
http://bWPU9HF7.dpqqg.cn
http://UlJevEiN.dpqqg.cn
http://7OUwbX20.dpqqg.cn
http://LWG1TIFW.dpqqg.cn
http://SBUM0UV6.dpqqg.cn
http://www.dtcms.com/a/386418.html

相关文章:

  • Three.js 开发实战教程(一):环境搭建与第一个 3D 场景
  • 旅游小程序的功能优势
  • LeetCode:7.接雨水
  • Android 安卓 问题解决记录 腾讯IM和厂商离线推送问题 点击离线推送无法唤醒APP启动页但某些Service服务和Application被启动
  • 动态规划解决系列子序列问题
  • SCADE One vs Scade 6 - 标量积建模比较
  • Next.js 身份验证与授权:使用 NextAuth.js 保护你的应用
  • Spring MVC 的案例小练习
  • 贪心算法与动态规划
  • 香港期权市场的主要参与者有哪些?
  • 系统中间件与云虚拟化-serverless-基于阿里云函数计算的简单邮件发送服务设计与体验
  • 【LLM】GPT-OSS架构变化详解
  • 【开题答辩全过程】以 “寄情绿苑”绿色殡葬服务小程序的设计和实现为例,包含答辩的问题和答案
  • 容器化部署之dockerfile07
  • 一篇读懂Pormise!!【前端ES6】
  • spring-kafka的消息过滤器RecordFilterStrategy
  • gin中sse流式服务
  • 论文笔记(九十一)GWM: Towards Scalable Gaussian World Models for Robotic Manipulation
  • Simulink(MATLAB)与 LabVIEW应用对比
  • [BX]和loop指令,debug和masm汇编编译器对指令的不同处理,循环,大小寄存器的包含关系,操作数据长度与寄存器的关系,段前缀
  • Django RBAC权限实战全流程
  • 智启燃气新未来丨众智鸿图精彩亮相2025燃气运营与安全研讨会
  • Docker Push 常见报错及解决方案汇总
  • OCR 后结构化处理最佳实践
  • 软考 系统架构设计师系列知识点之杂项集萃(148)
  • P1425 小鱼的游泳时间
  • 弧焊机器人氩气焊接节能方法
  • 机器人导论 第六章 动力学(2)——拉格朗日动力学推导与详述
  • 在uniapp中调用虚拟机调试vue项目
  • UE5 GAS 技能系统解析:EGameplayAbilityTriggerSource 枚举详解