每日 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 中静态方法和实例方法的区…...
【懒删除堆】力扣2349. 设计数字容器系统
设计一个数字容器系统,可以实现以下功能: 在系统中给定下标处 插入 或者 替换 一个数字。 返回 系统中给定数字的最小下标。 请你实现一个 NumberContainers 类: NumberContainers() 初始化数字容器系统。 void change(int index, int numb…...
【Block总结】OutlookAttention注意力,捕捉细节和局部特征|即插即用
论文信息 标题: VOLO: Vision Outlooker for Visual Recognition作者: Li Yuan, Qibin Hou, Zihang Jiang, Jiashi Feng, Shuicheng Yan代码链接: https://github.com/sail-sg/volo论文链接: https://arxiv.org/pdf/2106.13112 创新点 前景注意力机制: VOLO引入了一种称为“…...
有效运作神经网络
内容来自https://www.bilibili.com/video/BV1FT4y1E74V,仅为本人学习所用。 文章目录 训练集、验证集、测试集偏差、方差正则化正则化参数为什么正则化可以减少过拟合Dropout正则化Inverted Dropout其他的正则化方法数据增广Early stopping 归一化梯度消失与梯度爆…...
Vue 组件开发:构建高效可复用的前端界面要素
1 引言 在现代 Web 开发中,构建高效且可复用的前端界面要素是提升开发效率和用户体验的关键。Vue.js 作为一种轻量级且功能强大的前端框架,提供了丰富的工具和机制,帮助开发者快速构建高质量的应用程序。通过合理设计和封装 Vue 组件,我们可以实现组件的高效复用,提高开发…...
【Python】深入探索Python元类:动态生成类与对象的艺术
《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 元类是Python中一个高级且强大的特性,允许开发者在类的创建过程中插入自定义逻辑,从而动态生成类和对象。本文将全面介绍Python中的元类概…...
Spring Boot + Facade Pattern : 通过统一接口简化多模块业务
文章目录 Pre概述在编程中,外观模式是如何工作的?外观设计模式 UML 类图外观类和子系统的关系优点案例外观模式在复杂业务中的应用实战运用1. 项目搭建与基础配置2. 构建子系统组件航班服务酒店服务旅游套餐服务 3. 创建外观类4. 在 Controller 中使用外…...
在Linux系统上安装.NET
测试系统:openKylin(开放麒麟) 1.确定系统和架构信息: 打开终端(Ctrl Alt T),输入cat /etc/os-release查看系统版本相关信息。 输入uname -m查看系统架构。确保你的系统和架构符合.NET 的要求,如果架构…...
OpenAI Operator:AI Agent 大战的号角,从 “工具” 到 “助手” 的飞跃
想尝试不同的 AI 模型?不必到处寻找!chatTools 为您集成了 o1、GPT4o、Claude 和 Gemini 等多种选择,一个平台解决您的所有 AI 需求。现在就来体验吧! 各位 AI 爱好者们,今天我们来聊聊 OpenAI 的最新力作——Operator…...
AI大模型开发原理篇-9:GPT模型的概念和基本结构
基本概念 生成式预训练模型 GPT(Generative Pre-trained Transformer)模型 是由 OpenAI 开发的基于 Transformer 架构的自然语言处理(NLP)模型,专门用于文本生成任务。它的设计理念在于通过大规模的预训练来学习语言模…...
Java Swing 基础组件详解 [论文投稿-第四届智能系统、通信与计算机网络]
大会官网:www.icisccn.net Java Swing 是一个功能强大的 GUI 工具包,提供了丰富的组件库用于构建跨平台的桌面应用程序。本文将详细讲解 Swing 的基础组件,包括其作用、使用方法以及示例代码,帮助你快速掌握 Swing 的核心知识。 一…...
vscode+WSL2(ubuntu22.04)+pytorch+conda+cuda+cudnn安装系列
最近在家过年闲的没事,于是研究起深度学习开发工具链的配置和安装,之前欲与天公试比高,尝试在win上用vscodecuda11.6vs2019的cl编译器搭建cuda c编程环境,最后惨败,沦为笑柄,痛定思痛,这次直接和…...
【letta】The Letta Platform LETTA平台
The Letta Platform LETTA平台 The Letta Platform LETTA平台开源网站2023年的论文 论文:MemGPT Towards LLMs as Operating Systems Letta enables developers to build and deploy stateful AI agents - agents that maintain memory and context across long-running conve…...
想品客老师的第九天:原型和继承
原型与继承前置看这里 原型 原型都了解了,但是不是所有对象都有对象原型 let obj1 {}console.log(obj1)let obj2 Object.create(null, {name: {value: 荷叶饭}})console.log(obj2) obj2为什么没有对象原型?obj2是完全的数据字典对象,没有…...
Time Constant | RC、RL 和 RLC 电路中的时间常数
注:本文为 “Time Constant” 相关文章合辑。 机翻,未校。 How To Find The Time Constant in RC and RL Circuits June 8, 2024 💡 Key learnings: 关键学习点: Time Constant Definition: The time constant (τ) is define…...
原码、反码、补码以及lowbit运算
原码、反码、补码以及lowbit运算 原码: 可以用来计算正数加减,正数的原码、反码、补码都一样。 第一位为符号位,符号位0为正数,1为负数(32位字符,这里用4位来举例子,后面皆是用4位来举例子,其…...
芯片AI深度实战:实战篇之vim chat
利用vim-ollama这个vim插件,可以在vim内和本地大模型聊天。 系列文章: 芯片AI深度实战:基础篇之Ollama-CSDN博客 芯片AI深度实战:基础篇之langchain-CSDN博客 芯片AI深度实战:实战篇之vim chat-CSDN博客 芯片AI深度…...
当当网近30日热销图书的数据采集与可视化分析(scrapy+openpyxl+matplotlib)
当当网近30日热销图书的数据采集与可视化分析(scrapy+openpyxl+matplotlib) 当当网近30日热销书籍官网写在前面 实验目的:实现当当网近30日热销图书的数据采集与可视化分析。 电脑系统:Windows 使用软件:Visual Studio Code Python版本:python 3.12.4 技术需求:scrapy、…...
Spring Boot 日志:项目的“行车记录仪”
一、什么是Spring Boot日志 (一)日志引入 在正式介绍日志之前,我们先来看看上篇文章中(Spring Boot 配置文件)中的验证码功能的一个代码片段: 这是一段校验用户输入的验证码是否正确的后端代码,…...
幸运数字——蓝桥杯
1.问题描述 哈沙德数是指在某个固定的进位制当中,可以被各位数字之和整除的正整数。例如 126126 是十进制下的一个哈沙德数,因为 (126)10mod(126)0;126 也是八进制下的哈沙德数,因为 (126)10(176)8,(126)10mod(176)…...
Deepseek本地部署(ollama+open-webui)
ollama 首先是安装ollama,这个非常简单 https://ollama.com/ 下载安装即可 open-webui 这个是为了提供一个ui,毕竟我们也不想在cmd和模型交互,很不方便。 第一,需要安装python3.11,必须是3.11(其他版…...
【QT】 控件 -- 显示类
🔥 目录 [TOC]( 🔥 目录) 1. 前言 2. 显示类控件2.1 Label 1、显示不同文本2、显示图片3、文本对齐、自动换行、缩进、边距4、设置伙伴 3.2 LCD Number 3.3 ProgressBar 3.4 Calendar Widget 3. 共勉 🔥 1. 前言 之前我在上一篇文章【QT】…...
冲刺蓝桥杯之速通vector!!!!!
文章目录 知识点创建增删查改 习题1习题2习题3习题4:习题5: 知识点 C的STL提供已经封装好的容器vector,也可叫做可变长的数组,vector底层就是自动扩容的顺序表,其中的增删查改已经封装好 创建 const int N30; vecto…...
指针空值——nullptr(C++11)——提升指针安全性的利器
C11引入的nullptr是对指针空值的正式支持,它提供了比传统NULL指针更加安全和明确的指针空值表示方式。在C语言中,指针操作是非常基础且常见的,而如何安全地处理指针空值,一直是开发者关注的重要问题。本文将详细讲解nullptr的引入…...
鸿蒙开发黑科技“stack叠层”替代customdialog
前一篇提到的问题,本篇博文提出了一个解决方案: arkui-x LongPressGesture触发customdialog踩坑记录-CSDN博客 前一段时间遇到的这个问题,通过排除法观察,锁定为customdialog组件有bug,极为容易挂死。不论如何调整使用方法,都还是会触发挂死。 反馈给arkui团队,说是在…...
小米CR6606,CR6608,CR6609 启用SSH和刷入OpenWRT 23.05.5
闲鱼上收了一台CR6606和一台CR6609, 一直没时间研究, 趁春节假期把这两个都刷成 OpenWRT 配置说明 CPU: MT7621AT,双核880MHz内存: NT5CC128M16JR-EKI 或 M15T2G16128A, 256MB闪存: F59L1G81MB, 128MB无线基带芯片(BB): T7905DAN无线射频芯片(RF): MT7975DN无外置F…...
SpringCloud系列教程:微服务的未来(十八)雪崩问题、服务保护方案、Sentinel快速入门
前言 在分布式系统中,雪崩效应(Avalanche Effect)是一种常见的故障现象,通常发生在系统中某个组件出现故障时,导致其他组件级联失败,最终引发整个系统的崩溃。为了有效应对雪崩效应,服务保护方…...
Web-3.0(Solidity)ERC-20
🚀 发行自己的加密货币(ERC-20 代币) 你可以使用 Solidity 编写 ERC-20 智能合约 来发行自己的加密货币,然后部署到 以太坊(Ethereum) 或 BNB/Polygon 等 EVM 兼容链。 📌 1. ERC-20 代币是什么…...
大数据相关职位介绍之一(数据分析,数据开发,数据产品经理,数据运营)
大数据相关职位介绍之一 随着大数据、人工智能(AI)和机器学习的快速发展,数据分析与管理已经成为各行各业的重要组成部分。从互联网公司到传统行业的数字转型,数据相关职位在中国日益成为推动企业创新和提升竞争力的关键力量。以…...
无人机红外热成像:应急消防的“透视眼”
无人机红外热成像:应急消防的“透视眼” 亲爱的小伙伴们,每年一到夏天,应急消防的战士们就像上紧了发条的闹钟,时刻准备应对各种灾害。炎热天气让火灾隐患“蹭蹭”往上涨,南北各地还有防洪救灾、台风、泥石流等灾害轮…...
