每日 Java 面试题分享【第 17 天】

news2025/1/31 17:05:12

欢迎来到每日 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) 可突破限制,但违背封装原则。


高级应用与原理

  1. 类本身的修饰符

    • 顶级类(非内部类)只能用 public 或默认修饰符。
    • 内部类可任意使用四种修饰符(如 private static class Node 用于链表实现)。
  2. 构造方法的特殊修饰

    public class HttpClient {
        private HttpClient() {} // 强制通过工厂方法创建实例
        public static HttpClient create() { return new HttpClient(); }
    }
    
  3. 模块系统(Java 9+)
    即使成员是 public,若所在模块未导出对应包,其他模块仍无法访问(强化封装性)。


实战技巧

  • 最小权限原则:优先使用最严格的访问级别(如默认 > protected > public)。
  • 代码维护性private 方法更易重构,public 方法需谨慎设计避免破坏兼容性。
  • 测试考量:通过包结构组织测试类,合法访问默认和 protected 成员。

通过合理使用访问修饰符,可以有效控制代码的可见性,提升模块化设计和系统安全性。


问题二:Java 中静态方法和实例方法的区别是什么?


一、核心区别对比表(快速建立知识框架)

维度静态方法 (Static Method)实例方法 (Instance Method)
归属对象类级别(Class Level)对象级别(Object Level)
内存分配时机类加载时对象实例化时
调用方式ClassName.method()object.method()
隐含引用this 引用this 引用
多态支持静态绑定(编译时确定)动态绑定(运行时确定)
访问权限只能访问静态成员可访问静态 + 实例成员
线程安全考量需关注静态变量竞争实例变量隔离更易控制

二、底层原理深度解析

  1. JVM 内存模型差异

    • 静态方法:存储在方法区(JDK8+ 的元空间)的类元数据中
    • 实例方法:存储在堆内存的对象实例的方法表中
    // 示例:通过javap观察方法调用指令
    // 静态方法调用指令:invokestatic
    // 实例方法调用指令:invokevirtual/invokeinterface
    
  2. 方法分派机制

    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"(实例方法覆盖)
    }
    

三、实战应用场景分析

  1. 静态方法典型使用场景

    • 工具类方法(无状态操作)

      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); 
          }
      }
      
  2. 实例方法核心价值

    • 状态封装(对象特有行为)

      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();
      }
      

四、高频面试深挖点

  1. 为什么静态方法不能是抽象的?

    • 静态方法属于类级别,而抽象方法需要子类实现,存在根本性冲突
    • 替代方案:使用工厂模式或策略模式实现类似效果
  2. 静态方法是否可以被重写?

    • 严格说不存在重写(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(静态方法没有多态性)
      
  3. 如何选择方法类型?决策树

    是否需要访问实例变量?
    ├── 是 → 必须使用实例方法
    └── 否 → 是否与对象状态相关?
        ├── 是 → 仍建议实例方法
        └── 否 → 考虑静态方法
    

五、性能优化注意事项

  1. 内存占用对比

    • 静态方法:单份代码存储,无对象关联开销
    • 实例方法:每个对象持有方法表指针(HotSpot JVM 优化后实际共享代码)
  2. JIT 编译影响

    • 高频调用的静态方法更易被内联优化(无虚方法表查找)
  3. 并发安全黄金法则

    public class Counter {
        private static int count = 0;
        
        // 错误示范:静态方法操作静态变量未同步
        public static void unsafeIncrement() { count++; }
        
        // 正确方案:静态同步方法
        public static synchronized void safeIncrement() { count++; }
    }
    

六、设计模式中的典型应用

  1. 单例模式(静态工厂方法)

    public class Singleton {
        private static final Singleton INSTANCE = new Singleton();
        private Singleton() {}
        public static Singleton getInstance() { return INSTANCE; }
    }
    
  2. 策略模式(实例方法多态)

    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
集合迭代器效率更优
调试可见性可直接观察索引值无法直接获取当前索引
多维度遍历灵活控制嵌套层级需多层嵌套

二、底层原理深度解析

  1. 字节码层面对比(使用 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() 循环
  2. 数组遍历优化机制
    增强 for 循环在遍历数组时,编译器会优化为传统 for 循环:

    // 源代码
    int[] arr = {1,2,3};
    for(int num : arr){}
    
    // 编译器优化后等价于
    for(int i=0; i<arr.length; i++){
        int num = arr[i];
    }
    

三、实战场景选择指南

  1. 优先使用增强 for 循环的场景

    • 只读遍历集合/数组
    • 代码简洁性要求高
    • 需要避免 IndexOutOfBoundsException
    // 电商订单状态检查(无需修改集合)
    for(Order order : orderList){
        if(order.getStatus() == Status.PAID){
            sendShippingNotification(order);
        }
    }
    
  2. 必须使用传统 for 循环的场景

    • 需要删除/修改集合元素
    • 需要反向遍历
    • 需要访问相邻元素
    // 安全删除元素(使用迭代器模式)
    for(Iterator<Item> it = cartItems.iterator(); it.hasNext();){
        Item item = it.next();
        if(item.isExpired()){
            it.remove(); // 安全删除
        }
    }
    

四、性能关键指标对比

数据结构传统 for 循环时间复杂度增强 for 循环时间复杂度
ArrayListO(1) per accessO(1) via iterator
LinkedListO(n) per accessO(1) via iterator
HashSet不可用O(1) via iterator

性能测试数据(百万次遍历)

ArrayList:
- 传统for循环:12ms
- 增强for循环:15ms
- 迭代器遍历:18ms

LinkedList:
- 传统for循环:4200ms(灾难性性能)
- 增强for循环:28ms
- 迭代器遍历:25ms

五、高频面试深挖点

  1. 为什么增强 for 循环删除元素会抛异常?

    • 迭代器的 modCount 与集合的 expectedModCount 不一致触发快速失败机制
    • 解决方案:使用迭代器的 remove() 方法
  2. 如何实现自定义集合的增强 for 循环支持?

    • 实现 Iterable 接口并返回自定义 Iterator
    public class CustomCollection<T> implements Iterable<T> {
        // …其他代码
        @Override
        public Iterator<T> iterator() {
            return new CustomIterator();
        }
    }
    
  3. JDK9 对增强 for 循环的优化

    • 引入 ImmutableCollections 的优化迭代器
    • List.of() 创建的不可变集合进行遍历优化

六、设计模式与最佳实践

  1. 迭代器模式的应用
    增强 for 循环是迭代器模式的语法糖实现:

    // 等价代码解析
    for(Iterator<String> it = list.iterator(); it.hasNext();){
        String s = it.next();
        // 循环体
    }
    
  2. 防御性编程技巧

    // 遍历时检测集合是否被外部修改
    List<String> safeList = Collections.unmodifiableList(rawList);
    for(String s : safeList){ // 确保遍历过程不被修改
        process(s);
    }
    

总结回答模板
" 传统 for 循环与增强 for 循环的核心区别在于控制粒度和实现机制。在阿里高并发场景下,我们遵循:对 ArrayList 等随机访问集合优先使用传统 for 循环提升性能;对 LinkedList 等顺序访问集合必须使用增强 for 循环避免性能灾难。同时,在涉及集合修改时,统一使用迭代器删除模式保证线程安全。"


总结

今天的 3 道 Java 面试题,您是否掌握了呢?持续关注我们的每日分享,深入学习 Java 面试的各个细节,快速提升技术能力!如果有任何疑问,欢迎在评论区留言,我们会第一时间解答!

明天见!🎉

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2287001.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【懒删除堆】力扣2349. 设计数字容器系统

设计一个数字容器系统&#xff0c;可以实现以下功能&#xff1a; 在系统中给定下标处 插入 或者 替换 一个数字。 返回 系统中给定数字的最小下标。 请你实现一个 NumberContainers 类&#xff1a; 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&#xff0c;仅为本人学习所用。 文章目录 训练集、验证集、测试集偏差、方差正则化正则化参数为什么正则化可以减少过拟合Dropout正则化Inverted Dropout其他的正则化方法数据增广Early stopping 归一化梯度消失与梯度爆…

Vue 组件开发:构建高效可复用的前端界面要素

1 引言 在现代 Web 开发中,构建高效且可复用的前端界面要素是提升开发效率和用户体验的关键。Vue.js 作为一种轻量级且功能强大的前端框架,提供了丰富的工具和机制,帮助开发者快速构建高质量的应用程序。通过合理设计和封装 Vue 组件,我们可以实现组件的高效复用,提高开发…

Spring Boot + Facade Pattern : 通过统一接口简化多模块业务

文章目录 Pre概述在编程中&#xff0c;外观模式是如何工作的&#xff1f;外观设计模式 UML 类图外观类和子系统的关系优点案例外观模式在复杂业务中的应用实战运用1. 项目搭建与基础配置2. 构建子系统组件航班服务酒店服务旅游套餐服务 3. 创建外观类4. 在 Controller 中使用外…

OpenAI Operator:AI Agent 大战的号角,从 “工具” 到 “助手” 的飞跃

想尝试不同的 AI 模型&#xff1f;不必到处寻找&#xff01;chatTools 为您集成了 o1、GPT4o、Claude 和 Gemini 等多种选择&#xff0c;一个平台解决您的所有 AI 需求。现在就来体验吧&#xff01; 各位 AI 爱好者们&#xff0c;今天我们来聊聊 OpenAI 的最新力作——Operator…

AI大模型开发原理篇-9:GPT模型的概念和基本结构

基本概念 生成式预训练模型 GPT&#xff08;Generative Pre-trained Transformer&#xff09;模型 是由 OpenAI 开发的基于 Transformer 架构的自然语言处理&#xff08;NLP&#xff09;模型&#xff0c;专门用于文本生成任务。它的设计理念在于通过大规模的预训练来学习语言模…

Java Swing 基础组件详解 [论文投稿-第四届智能系统、通信与计算机网络]

大会官网&#xff1a;www.icisccn.net Java Swing 是一个功能强大的 GUI 工具包&#xff0c;提供了丰富的组件库用于构建跨平台的桌面应用程序。本文将详细讲解 Swing 的基础组件&#xff0c;包括其作用、使用方法以及示例代码&#xff0c;帮助你快速掌握 Swing 的核心知识。 一…

vscode+WSL2(ubuntu22.04)+pytorch+conda+cuda+cudnn安装系列

最近在家过年闲的没事&#xff0c;于是研究起深度学习开发工具链的配置和安装&#xff0c;之前欲与天公试比高&#xff0c;尝试在win上用vscodecuda11.6vs2019的cl编译器搭建cuda c编程环境&#xff0c;最后惨败&#xff0c;沦为笑柄&#xff0c;痛定思痛&#xff0c;这次直接和…

想品客老师的第九天:原型和继承

原型与继承前置看这里 原型 原型都了解了&#xff0c;但是不是所有对象都有对象原型 let obj1 {}console.log(obj1)let obj2 Object.create(null, {name: {value: 荷叶饭}})console.log(obj2) obj2为什么没有对象原型&#xff1f;obj2是完全的数据字典对象&#xff0c;没有…

Time Constant | RC、RL 和 RLC 电路中的时间常数

注&#xff1a;本文为 “Time Constant” 相关文章合辑。 机翻&#xff0c;未校。 How To Find The Time Constant in RC and RL Circuits June 8, 2024 &#x1f4a1; Key learnings: 关键学习点&#xff1a; Time Constant Definition: The time constant (τ) is define…

芯片AI深度实战:实战篇之vim chat

利用vim-ollama这个vim插件&#xff0c;可以在vim内和本地大模型聊天。 系列文章&#xff1a; 芯片AI深度实战&#xff1a;基础篇之Ollama-CSDN博客 芯片AI深度实战&#xff1a;基础篇之langchain-CSDN博客 芯片AI深度实战&#xff1a;实战篇之vim chat-CSDN博客 芯片AI深度…

Spring Boot 日志:项目的“行车记录仪”

一、什么是Spring Boot日志 &#xff08;一&#xff09;日志引入 在正式介绍日志之前&#xff0c;我们先来看看上篇文章中&#xff08;Spring Boot 配置文件&#xff09;中的验证码功能的一个代码片段&#xff1a; 这是一段校验用户输入的验证码是否正确的后端代码&#xff0c…

【QT】 控件 -- 显示类

&#x1f525; 目录 [TOC]( &#x1f525; 目录) 1. 前言 2. 显示类控件2.1 Label 1、显示不同文本2、显示图片3、文本对齐、自动换行、缩进、边距4、设置伙伴 3.2 LCD Number 3.3 ProgressBar 3.4 Calendar Widget 3. 共勉 &#x1f525; 1. 前言 之前我在上一篇文章【QT】…

冲刺蓝桥杯之速通vector!!!!!

文章目录 知识点创建增删查改 习题1习题2习题3习题4&#xff1a;习题5&#xff1a; 知识点 C的STL提供已经封装好的容器vector&#xff0c;也可叫做可变长的数组&#xff0c;vector底层就是自动扩容的顺序表&#xff0c;其中的增删查改已经封装好 创建 const int N30; vecto…

小米CR6606,CR6608,CR6609 启用SSH和刷入OpenWRT 23.05.5

闲鱼上收了一台CR6606和一台CR6609, 一直没时间研究, 趁春节假期把这两个都刷成 OpenWRT 配置说明 CPU: MT7621AT&#xff0c;双核880MHz内存: NT5CC128M16JR-EKI 或 M15T2G16128A, 256MB闪存: F59L1G81MB, 128MB无线基带芯片(BB): T7905DAN无线射频芯片(RF): MT7975DN无外置F…

SpringCloud系列教程:微服务的未来(十八)雪崩问题、服务保护方案、Sentinel快速入门

前言 在分布式系统中&#xff0c;雪崩效应&#xff08;Avalanche Effect&#xff09;是一种常见的故障现象&#xff0c;通常发生在系统中某个组件出现故障时&#xff0c;导致其他组件级联失败&#xff0c;最终引发整个系统的崩溃。为了有效应对雪崩效应&#xff0c;服务保护方…

大数据相关职位介绍之一(数据分析,数据开发,数据产品经理,数据运营)

大数据相关职位介绍之一 随着大数据、人工智能&#xff08;AI&#xff09;和机器学习的快速发展&#xff0c;数据分析与管理已经成为各行各业的重要组成部分。从互联网公司到传统行业的数字转型&#xff0c;数据相关职位在中国日益成为推动企业创新和提升竞争力的关键力量。以…

无人机红外热成像:应急消防的“透视眼”

无人机红外热成像&#xff1a;应急消防的“透视眼” 亲爱的小伙伴们&#xff0c;每年一到夏天&#xff0c;应急消防的战士们就像上紧了发条的闹钟&#xff0c;时刻准备应对各种灾害。炎热天气让火灾隐患“蹭蹭”往上涨&#xff0c;南北各地还有防洪救灾、台风、泥石流等灾害轮…

【狂热算法篇】探秘图论之Dijkstra 算法:穿越图的迷宫的最短路径力量(通俗易懂版)

羑悻的小杀马特.-CSDN博客羑悻的小杀马特.擅长C/C题海汇总,AI学习,c的不归之路,等方面的知识,羑悻的小杀马特.关注算法,c,c语言,青少年编程领域.https://blog.csdn.net/2401_82648291?typebbshttps://blog.csdn.net/2401_82648291?typebbshttps://blog.csdn.net/2401_8264829…