每日 Java 面试题分享【第 17 天】
欢迎来到每日 Java 面试题分享栏目!
订阅专栏,不错过每一天的练习
今日分享 3 道面试题目!
评论区复述一遍印象更深刻噢~
目录
- 问题一:Java 中的访问修饰符有哪些?
- 问题二:Java 中静态方法和实例方法的区别是什么?
- 问题三:Java 中 for 循环与 foreach 循环的区别是什么?
问题一:Java 中的访问修饰符有哪些?
在 Java 中,访问修饰符用于控制类、变量、方法和构造方法的可见性范围。以下是 Java 的四种访问修饰符及其作用域,结合代码示例和底层原理进行说明:
访问修饰符分类及作用域
修饰符 | 类内部 | 同包其他类 | 不同包子类 | 不同包非子类 |
---|---|---|---|---|
public | ✔️ | ✔️ | ✔️ | ✔️ |
protected | ✔️ | ✔️ | ✔️ | ❌ |
默认(无修饰符) | ✔️ | ✔️ | ❌ | ❌ |
private | ✔️ | ❌ | ❌ | ❌ |
1. public:全局可见
-
作用范围:所有类均可访问。
-
使用场景:开放 API 方法或常量。
-
代码示例:
public class Logger {public static final String LEVEL = "DEBUG"; // 所有类可访问public void log(String message) { /* 实现 */ } }
-
底层原理:编译时无访问限制检查,JVM 通过符号引用直接访问。
2. protected:继承体系可见
-
作用范围:同包类 + 不同包的子类(需通过继承访问)。
-
关键细节:不同包子类中,只能访问从父类继承的
protected
成员,不能直接访问其他父类实例的成员。 -
代码示例:
// 包 com.example; public class Base {protected void init() { /* 初始化逻辑 */ } }// 包 com.other; public class Sub extends Base {void test() {init(); // ✔️ 允许(继承访问)new Base().init(); // ❌ 编译错误(直接访问其他实例)} }
-
设计意义:支持模板方法模式,允许子类扩展特定步骤。
3. 默认(包级私有):同包可见
-
作用范围:仅限同包内类访问。
-
使用场景:包内工具类或组件间协作。
-
代码示例:
class PackagePrivateUtils { // 默认修饰符static void helper() { /* 包内共享工具方法 */ } }
-
底层原理:编译器在跨包访问时校验类权限,阻止外部包通过全限定名访问。
4. private:类内封闭
-
作用范围:仅限当前类内部。
-
使用场景:封装对象状态或内部工具方法。
-
代码示例:
public class Singleton {private static Singleton instance; // 私有静态变量private Singleton() {} // 私有构造方法public static Singleton getInstance() { /* 提供全局访问点 */ } }
-
反射限制:通过
setAccessible(true)
可突破限制,但违背封装原则。
高级应用与原理
-
类本身的修饰符:
- 顶级类(非内部类)只能用
public
或默认修饰符。 - 内部类可任意使用四种修饰符(如
private static class Node
用于链表实现)。
- 顶级类(非内部类)只能用
-
构造方法的特殊修饰:
public class HttpClient {private HttpClient() {} // 强制通过工厂方法创建实例public static HttpClient create() { return new HttpClient(); } }
-
模块系统(Java 9+):
即使成员是public
,若所在模块未导出对应包,其他模块仍无法访问(强化封装性)。
实战技巧
- 最小权限原则:优先使用最严格的访问级别(如默认 > protected > public)。
- 代码维护性:
private
方法更易重构,public
方法需谨慎设计避免破坏兼容性。 - 测试考量:通过包结构组织测试类,合法访问默认和
protected
成员。
通过合理使用访问修饰符,可以有效控制代码的可见性,提升模块化设计和系统安全性。
问题二:Java 中静态方法和实例方法的区别是什么?
一、核心区别对比表(快速建立知识框架)
维度 | 静态方法 (Static Method) | 实例方法 (Instance Method) |
---|---|---|
归属对象 | 类级别(Class Level) | 对象级别(Object Level) |
内存分配时机 | 类加载时 | 对象实例化时 |
调用方式 | ClassName.method() | object.method() |
隐含引用 | 无 this 引用 | 有 this 引用 |
多态支持 | 静态绑定(编译时确定) | 动态绑定(运行时确定) |
访问权限 | 只能访问静态成员 | 可访问静态 + 实例成员 |
线程安全考量 | 需关注静态变量竞争 | 实例变量隔离更易控制 |
二、底层原理深度解析
-
JVM 内存模型差异
- 静态方法:存储在方法区(JDK8+ 的元空间)的类元数据中
- 实例方法:存储在堆内存的对象实例的方法表中
// 示例:通过javap观察方法调用指令 // 静态方法调用指令:invokestatic // 实例方法调用指令:invokevirtual/invokeinterface
-
方法分派机制
class Parent {static void staticMethod() { System.out.println("Parent static"); }void instanceMethod() { System.out.println("Parent instance"); } }class Child extends Parent {static void staticMethod() { System.out.println("Child static"); }@Override void instanceMethod() { System.out.println("Child instance"); } }public static void main(String[] args) {Parent p = new Child();p.staticMethod(); // 输出"Parent static"(静态方法隐藏)p.instanceMethod(); // 输出"Child instance"(实例方法覆盖) }
三、实战应用场景分析
-
静态方法典型使用场景
-
工具类方法(无状态操作)
public final class StringUtils {private StringUtils() {} // 防止实例化public static boolean isEmpty(String str) { return str == null || str.trim().isEmpty();} }
-
工厂模式
public class ConnectionFactory {public static Connection create() { return DriverManager.getConnection(url); } }
-
-
实例方法核心价值
-
状态封装(对象特有行为)
public class Order {private double amount;public void applyDiscount(double rate) { // 操作实例状态this.amount *= (1 - rate);} }
-
模板方法模式
public abstract class PaymentProcessor {public final void process() { // 实例方法控制流程validate();executePayment();sendNotification();}protected abstract void executePayment(); }
-
四、高频面试深挖点
-
为什么静态方法不能是抽象的?
- 静态方法属于类级别,而抽象方法需要子类实现,存在根本性冲突
- 替代方案:使用工厂模式或策略模式实现类似效果
-
静态方法是否可以被重写?
-
严格说不存在重写(Override),只有隐藏(Hide)
-
示例说明:
class Animal { static void eat() { System.out.println("Animal eating"); } } class Dog extends Animal { static void eat() { System.out.println("Dog eating"); } }Animal myDog = new Dog(); myDog.eat(); // 输出Animal eating(静态方法没有多态性)
-
-
如何选择方法类型?决策树
是否需要访问实例变量? ├── 是 → 必须使用实例方法 └── 否 → 是否与对象状态相关?├── 是 → 仍建议实例方法└── 否 → 考虑静态方法
五、性能优化注意事项
-
内存占用对比
- 静态方法:单份代码存储,无对象关联开销
- 实例方法:每个对象持有方法表指针(HotSpot JVM 优化后实际共享代码)
-
JIT 编译影响
- 高频调用的静态方法更易被内联优化(无虚方法表查找)
-
并发安全黄金法则
public class Counter {private static int count = 0;// 错误示范:静态方法操作静态变量未同步public static void unsafeIncrement() { count++; }// 正确方案:静态同步方法public static synchronized void safeIncrement() { count++; } }
六、设计模式中的典型应用
-
单例模式(静态工厂方法)
public class Singleton {private static final Singleton INSTANCE = new Singleton();private Singleton() {}public static Singleton getInstance() { return INSTANCE; } }
-
策略模式(实例方法多态)
public interface PaymentStrategy {void pay(double amount); // 实例方法实现多态 }public class AlipayStrategy implements PaymentStrategy {@Override public void pay(double amount) { /* 具体实现 */ } }
总结回答模板:
" 静态方法与实例方法的本质区别在于方法归属与状态绑定。静态方法属于类层级,在类加载时初始化,适用于工具类和工厂模式;实例方法绑定对象实例,支持多态和状态操作。在阿里中间件开发中,我们严格遵循:操作对象状态必须用实例方法,全局工具方法用静态方法,并通过 Sonar 代码检测确保规范执行。"
问题三:Java 中 for 循环与 foreach 循环的区别是什么?
一、核心区别对比表(快速建立知识框架)
维度 | 传统 for 循环 (for(int i=0;…) ) | 增强 for 循环 (for(E e: collection) ) |
---|---|---|
语法复杂度 | 显式控制索引/迭代器 | 隐式迭代(语法糖) |
底层实现 | 数组:直接索引访问 集合:可能低效遍历 | 数组:编译为传统 for 集合:迭代器模式 |
代码安全性 | 需手动控制边界 | 自动处理越界 |
集合修改能力 | 可通过索引或迭代器安全删除 | 直接删除会抛 ConcurrentModificationException |
性能差异 | 数组遍历快(CPU 缓存优化) LinkedList 慢 | 数组同传统 for 集合迭代器效率更优 |
调试可见性 | 可直接观察索引值 | 无法直接获取当前索引 |
多维度遍历 | 灵活控制嵌套层级 | 需多层嵌套 |
二、底层原理深度解析
-
字节码层面对比(使用 javap 反编译验证)
// 示例代码 List<String> list = Arrays.asList("a", "b");// 传统for循环(集合遍历) for(int i=0; i<list.size(); i++){String s = list.get(i); }// 增强for循环(集合遍历) for(String s : list){}
反编译关键指令:
- 传统 for 循环:
iload
(加载索引) +aload
(加载集合) +invokeinterface
(调用 get) - 增强 for 循环:
invokeinterface
(获取迭代器) +hasNext()
/next()
循环
- 传统 for 循环:
-
数组遍历优化机制
增强 for 循环在遍历数组时,编译器会优化为传统 for 循环:// 源代码 int[] arr = {1,2,3}; for(int num : arr){}// 编译器优化后等价于 for(int i=0; i<arr.length; i++){int num = arr[i]; }
三、实战场景选择指南
-
优先使用增强 for 循环的场景
- 只读遍历集合/数组
- 代码简洁性要求高
- 需要避免
IndexOutOfBoundsException
// 电商订单状态检查(无需修改集合) for(Order order : orderList){if(order.getStatus() == Status.PAID){sendShippingNotification(order);} }
-
必须使用传统 for 循环的场景
- 需要删除/修改集合元素
- 需要反向遍历
- 需要访问相邻元素
// 安全删除元素(使用迭代器模式) for(Iterator<Item> it = cartItems.iterator(); it.hasNext();){Item item = it.next();if(item.isExpired()){it.remove(); // 安全删除} }
四、性能关键指标对比
数据结构 | 传统 for 循环时间复杂度 | 增强 for 循环时间复杂度 |
---|---|---|
ArrayList | O(1) per access | O(1) via iterator |
LinkedList | O(n) per access | O(1) via iterator |
HashSet | 不可用 | O(1) via iterator |
性能测试数据(百万次遍历):
ArrayList:
- 传统for循环:12ms
- 增强for循环:15ms
- 迭代器遍历:18msLinkedList:
- 传统for循环:4200ms(灾难性性能)
- 增强for循环:28ms
- 迭代器遍历:25ms
五、高频面试深挖点
-
为什么增强 for 循环删除元素会抛异常?
- 迭代器的
modCount
与集合的expectedModCount
不一致触发快速失败机制 - 解决方案:使用迭代器的
remove()
方法
- 迭代器的
-
如何实现自定义集合的增强 for 循环支持?
- 实现
Iterable
接口并返回自定义Iterator
public class CustomCollection<T> implements Iterable<T> {// …其他代码@Overridepublic Iterator<T> iterator() {return new CustomIterator();} }
- 实现
-
JDK9 对增强 for 循环的优化
- 引入
ImmutableCollections
的优化迭代器 - 对
List.of()
创建的不可变集合进行遍历优化
- 引入
六、设计模式与最佳实践
-
迭代器模式的应用
增强 for 循环是迭代器模式的语法糖实现:// 等价代码解析 for(Iterator<String> it = list.iterator(); it.hasNext();){String s = it.next();// 循环体 }
-
防御性编程技巧
// 遍历时检测集合是否被外部修改 List<String> safeList = Collections.unmodifiableList(rawList); for(String s : safeList){ // 确保遍历过程不被修改process(s); }
总结回答模板:
" 传统 for 循环与增强 for 循环的核心区别在于控制粒度和实现机制。在阿里高并发场景下,我们遵循:对 ArrayList 等随机访问集合优先使用传统 for 循环提升性能;对 LinkedList 等顺序访问集合必须使用增强 for 循环避免性能灾难。同时,在涉及集合修改时,统一使用迭代器删除模式保证线程安全。"
总结
今天的 3 道 Java 面试题,您是否掌握了呢?持续关注我们的每日分享,深入学习 Java 面试的各个细节,快速提升技术能力!如果有任何疑问,欢迎在评论区留言,我们会第一时间解答!
明天见!🎉
相关文章:
每日 Java 面试题分享【第 17 天】
欢迎来到每日 Java 面试题分享栏目! 订阅专栏,不错过每一天的练习 今日分享 3 道面试题目! 评论区复述一遍印象更深刻噢~ 目录 问题一:Java 中的访问修饰符有哪些?问题二:Java 中静态方法和实例方法的区…...

「全网最细 + 实战源码案例」设计模式——桥接模式
核心思想 桥接模式(Bridge Pattern)是一种结构型设计模式,将抽象部分与其实现部分分离,使它们可以独立变化。降低代码耦合度,避免类爆炸,提高代码的可扩展性。 结构 1. Implementation(实现类…...

JavaScript 进阶(上)
作用域 局部作用域 局部作用域分为函数作用域和块作用域。 函数作用域: 在函数内部声明的变量只能在函数内部被访问,外部无法直接访问。 总结: 函数内部声明的变量,在函数外部无法被访问 函数的参数也是函数内部的局部变量 …...

【编译原理实验二】——自动机实验:NFA转DFA并最小化
本篇适用于ZZU的编译原理课程实验二——自动机实验:NFA转DFA并最小化,包含了实验代码和实验报告的内容,读者可根据需要参考完成自己的程序设计。 如果是ZZU的学弟学妹看到这篇,那么恭喜你,你来对地方啦! 如…...
深入探讨:服务器如何响应前端请求及后端如何查看前端提交的数据
深入探讨:服务器如何响应前端请求及后端如何查看前端提交的数据 一、服务器如何响应前端请求 前端与后端的交互主要通过 HTTP 协议实现。以下是详细步骤: 1. 前端发起 HTTP 请求 GET 请求:用于从服务器获取数据。POST 请求:用…...
如何利用Docker和.NET Core实现环境一致性、简化依赖管理、快速部署与扩展,同时提高资源利用率、确保安全性和生态系统支持
目录 1. 环境一致性 2. 简化依赖管理 3. 快速部署与扩展 4. 提高资源利用率 5. 确保安全性 6. 生态系统支持 总结 使用 Docker 和 .NET Core 结合,可以有效地实现环境一致性、简化依赖管理、快速部署与扩展,同时提高资源利用率、确保安全性和生态…...
@Inject @Qualifier @Named
Inject Qualifier Named 在依赖注入(DI)中,Inject、Qualifier 和 Named 是用于管理对象创建和绑定的关键注解。以下是它们的用途、依赖配置和代码示例的详细说明: 1. 注解的作用 Inject:标记需要注入的构造函数、字段…...
创建 priority_queue - 进阶(内置类型)c++
内置类型就是 C 提供的数据类型,⽐如 int 、 double 、 long long 等。以 int 类型为例,分 别创建⼤根堆和⼩根堆。 这种写法意思是,我要告诉这个优先级队列要建一个什么样的堆,第一个int是要存什么数据类型,vecto…...

2. Java-MarkDown文件解析-工具类
2. Java-MarkDown文件解析-工具类 1. 思路 读取markdown文件的内容,根据markdown的语法进行各个类型语法的解析。引入工具类 commonmark 和 commonmark-ext-gfm-tables进行markdown语法解析。 2. 工具类 pom.xml <!-- commonmark 解析markdown --> <d…...

动态规划DP 最长上升子序列模型 登山(题目分析+C++完整代码)
概览检索 动态规划DP 最长上升子序列模型 登山 原题链接 AcWing 1014. 登山 题目描述 五一到了,ACM队组织大家去登山观光,队员们发现山上一共有N个景点,并且决定按照顺序来浏览这些景点,即每次所浏览景点的编号都要大于前一个…...
css-设置元素的溢出行为为可见overflow: visible;
1.前言 overflow 属性用于设置当元素的内容溢出其框时如何处理。 2. overflow overflow 属性的一些常见值: 1 visible:默认值。内容不会被剪裁,会溢出元素的框。 2 hidden:内容会被剪裁,不会显示溢出的部分。 3 sc…...

家居EDI:Hom Furniture EDI需求分析
HOM Furniture 是一家成立于1977年的美国家具零售商,总部位于明尼苏达州。公司致力于提供高品质、时尚的家具和家居用品,满足各种家庭和办公需求。HOM Furniture 以广泛的产品线和优质的客户服务在市场上赢得了良好的口碑。公司经营的产品包括卧室、客厅…...

1、开始简单使用rag
文章目录 前言数据存放申请api开始代码安装依赖从文件夹中读取文档文档切块将分割嵌入并存储在向量库中检索部分代码构造用户接口演示提示 整体代码 前言 本章只是简单使用rag的一个示例,为了引出以后的学习,将整个rag的流程串起来 数据存放 一个示例…...

Linux Samba 低版本漏洞(远程控制)复现与剖析
目录 前言 漏洞介绍 漏洞原理 产生条件 漏洞影响 防御措施 复现过程 结语 前言 在网络安全的复杂生态中,系统漏洞的探索与防范始终是保障数字世界安全稳定运行的关键所在。Linux Samba 作为一款在网络共享服务领域应用极为广泛的软件,其低版本中…...

安卓(android)实现注册界面【Android移动开发基础案例教程(第2版)黑马程序员】
一、实验目的(如果代码有错漏,可查看源码) 1.掌握LinearLayout、RelativeLayout、FrameLayout等布局的综合使用。 2.掌握ImageView、TextView、EditText、CheckBox、Button、RadioGroup、RadioButton、ListView、RecyclerView等控件在项目中的…...
【 AI agents】letta:2024年代理堆栈演进(中英文翻译)
The AI agents stack AI 代理堆栈 November 14, 2024 11月 14, 2024原文: The AI agents stack官方教程教程学习笔记: 【memgpt】letta 课程1/2:从头实现一个自我编辑、记忆和多步骤推理的代理Understanding the AI agents landscape 了解 AI 代理环境 Although we see a …...

Java中 instanceof 的用法(详解)
目录 引言 基本语法 基本作用 1. 检查对象是否是指定类的实例 2. 检查对象是否是子类的实例 3. 检查对象是否实现某个接口 4.null 处理 错误分析: 5.综合对比示例 最后总结 注意事项 引言 instanceof 概念在多态中引出,因为在多态发生时&…...

联想拯救者R720笔记本外接显示屏方法,显示屏是2K屏27英寸
晚上23点10分前下单,第二天上午显示屏送到,检查外包装没拆封过。这个屏幕左下方有几个按键,按一按就开屏幕、按一按就关闭屏幕,按一按方便节省时间,也支持阅读等模式。 显示屏是 :AOC 27英寸 2K高清 100Hz…...
【RocketMQ 存储】- 一文总结 RocketMQ 的存储结构-基础
文章目录 1. 前言 本文章基于 RocketMQ 4.9.3 1. 前言 RocketMQ 存储部分系列文章: 【RocketMQ 存储】- RocketMQ存储类 MappedFile 【RocketMQ 存储】- 一文总结 RocketMQ 的存储结构-基础 【RocketMQ 存储】- 一文总结 RocketMQ 的存储结构-基础...

S4 HANA明确税金本币和外币之间转换汇率确定(OBC8)
本文主要介绍在S4 HANA OP中明确明确税金本币和外币之间转换汇率确定(OBC8)相关设置。具体请参照如下内容: 明确税金本币和外币之间转换汇率确定(OBC8) 以上配置,我们可以根据不同公司代码所配置的使用不同的汇率来对税金外币和本币之间进行换算。来针对…...

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...
rknn优化教程(二)
文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...
React hook之useRef
React useRef 详解 useRef 是 React 提供的一个 Hook,用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途,下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...

VB.net复制Ntag213卡写入UID
本示例使用的发卡器:https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...
从零实现富文本编辑器#5-编辑器选区模型的状态结构表达
先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...

云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地
借阿里云中企出海大会的东风,以**「云启出海,智联未来|打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办,现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...

Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)
概述 在 Swift 开发语言中,各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过,在涉及到多个子类派生于基类进行多态模拟的场景下,…...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)
可以使用Sqliteviz这个网站免费编写sql语句,它能够让用户直接在浏览器内练习SQL的语法,不需要安装任何软件。 链接如下: sqliteviz 注意: 在转写SQL语法时,关键字之间有一个特定的顺序,这个顺序会影响到…...

ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放
简介 前面两期文章我们介绍了I2S的读取和写入,一个是通过INMP441麦克风模块采集音频,一个是通过PCM5102A模块播放音频,那如果我们将两者结合起来,将麦克风采集到的音频通过PCM5102A播放,是不是就可以做一个扩音器了呢…...

多种风格导航菜单 HTML 实现(附源码)
下面我将为您展示 6 种不同风格的导航菜单实现,每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...