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

【模拟面试|豆包模拟面试-1 Java基础】

还没针对性 去背八股 纯靠之前记得多少 效果不是很理想 基础题答的都很乱

Java 基础面试完整笔记(问题 + 我的回答 + 标准答案 + 指导)

1. 问题:Java 中基本数据类型都有哪些,它们各自的特点是什么?

我的回答

有整数类型、浮点类型,还有引用类型。整数类型分为 int、long,然后还有浮点类型 float 跟 BYTE,然后还有字符型、布尔值。❌

标准答案

Java 的基本数据类型共 8 种,无引用类型(引用类型是类、接口、数组等,不属于基本类型),具体分类及特点如下:

类型字节数取值范围 / 特点
整数型
byte1-128~127,最小整数类型
short2-32768~32767
int4-2³¹~2³¹-1(最常用整数类型)
long8-2⁶³~2⁶³-1,需加后缀 L(如 10L)
浮点型
float4单精度,需加后缀 F(如 3.14F),精度有限
double8双精度,默认浮点类型(如 3.14),精度更高
字符型
char2存储 Unicode 字符(如 'a'、' 中 '),取值 0~65535
布尔型
boolean未明确仅 true/false,虚拟机实现为 1 位或 1 字节

指导

  • 易错点:混淆 “基本类型” 与 “引用类型”,漏记 byte、short;将 byte 误归为字符串类型。
  • 改进:用 “分类记忆法”(整数、浮点、字符、布尔)记全 8 种,重点记住字节数和关键后缀(long 加 L、float 加 F)。

2. 问题:int 类型在内存中占几个字节,取值范围是多少?

我的回答

占 4 个字节,取值范围是 - 128 到 17。❌

标准答案

  • 字节数:4 个字节(32 位)
  • 取值范围:-2³¹(-2147483648)~ 2³¹-1(2147483647)

指导

  • 易错点:取值范围完全记混(-128 是 byte 的最小值)。
  • 改进:关联 “字节数→位数→取值范围” 逻辑:4 字节 = 32 位,1 位符号位,31 位数值位,故最小值为 - 2³¹,最大值为 2³¹-1,通过公式辅助记忆。

3. 问题:Java 中的字符串类型有哪些,它们之间有什么区别?

我的回答

Java 中的字符串类型有 byte 跟 string,byte 的话是字节型字符串类型,string 是一个对象。❌

标准答案

Java 中核心字符串相关类型为 3 种(byte 是基本数据类型,非字符串类型):

类型不可变性线程安全效率核心场景
String不可变安全字符串常量、少量拼接
StringBuilder可变不安全单线程频繁字符串拼接
StringBuffer可变安全(synchronized 修饰)多线程频繁字符串拼接

指导

  • 易错点:将 byte 误判为字符串类型;混淆 StringBuffer 与 StringBuilder 的线程安全和效率顺序。
  • 改进:先明确 “byte≠字符串类型”,再用 “不可变性→线程安全→效率” 的逻辑链记忆,重点记住:String 不可变(拼接创建新对象)、StringBuffer 安全但慢、StringBuilder 不安全但快。

4. 问题:什么是封装,在 Java 中如何体现?

我的回答

封装就是面向对象三个重要特点之一,封装需要把...(未说完)❌

标准答案

  • 定义:将对象的属性(数据)和操作属性的方法封装在一起,隐藏内部实现细节,仅对外暴露必要的访问接口(getter/setter),保护数据安全性。
  • Java 中的体现:
    1. 成员变量用private修饰(禁止外部直接访问);
    2. 提供public的 getter 方法(获取属性值)和 setter 方法(修改属性值,可添加逻辑校验);
    3. 示例:

      java

      运行

      class User {private String name; // 私有属性,隐藏细节public String getName() { return name; } // 暴露获取接口public void setName(String name) {if (name != null && !name.isEmpty()) { // 逻辑校验this.name = name;}}
      }
      

指导

  • 不足:仅知道是面向对象特性,未说清 “隐藏细节 + 暴露接口” 的核心,也未说明实现方式。
  • 改进:记住封装的 “目的(保护数据)+ 实现步骤(private 修饰属性 + public getter/setter)”,结合示例理解。

5. 问题:继承在 Java 中又是怎样的呢?

我的回答

继承就是实现它的父类,然后用一个 override 的方法实现它,如果父类是抽象类的话,就必须要实现它的所有方法。

标准答案

  • 定义:子类通过extends关键字继承父类的非私有属性和方法,实现代码复用,建立类的层级关系(如 Animal→Dog)。
  • 核心规则:
    1. Java 单继承:一个子类只能继承一个父类(但可多层继承,如 Dog→Animal→Object);
    2. 重写(@Override):子类可重写父类的非静态方法,方法名、参数列表、返回值类型需完全一致(子类返回值可是父类的子类型);
    3. 抽象类继承:子类继承抽象类(abstract class),必须实现所有抽象方法(除非子类也是抽象类)。

指导

  • 不足:未提及extends关键字、单继承规则;对重写的语法规则描述不完整。
  • 改进:重点记忆 “单继承 + 重写三要素 + 抽象类实现要求”,结合 “父类 Animal,子类 Dog 重写 eat () 方法” 的示例。

6. 问题:多态又该怎么理解呢?

我的回答

多态就是父类可以引用子类的方法,子类也可以变成父类,就是上下兼容,向下转型的话要注意。

标准答案

  • 定义:同一行为在不同对象上有不同表现形式,核心是 “父类引用指向子类对象”。
  • 实现条件
    1. 存在继承关系;
    2. 子类重写父类方法;
    3. 父类引用指向子类对象(向上转型)。
  • 核心规则
    1. 向上转型(自动):Parent p = new Child();,只能调用父类声明的方法(实际执行子类重写的实现);
    2. 向下转型(强制):需用instanceof判断类型,避免ClassCastException,如:

      java

      运行

      if (p instanceof Child) {Child c = (Child) p; // 安全转型c.childMethod(); // 调用子类特有方法
      }
      

指导

  • 不足:未说明多态的实现条件(继承、重写、父类引用);对向下转型的instanceof判断未提及。
  • 改进:用 “Animal p = new Dog (); p.eat ();” 示例理解向上转型,记住 “向下转型必须先判断类型” 的核心要求。

7. 问题:public、private、protected 和默认修饰符(不写)有什么区别?

我的回答

Public 就是公共类,所有都能访问到。private 就是只有当前类才能访问到。protected 是只有当前包可以访问到,类访问不到。 不写的话默认是 default,跟 public 一样。❌

标准答案

修饰符本类同包子类(不同包)其他包
public
protected×
default××
private×××

指导

  • 易错点:protected 允许不同包子类访问;default 仅同包可访问,与 public 完全不同。
  • 改进:用 “表格记忆法”,重点标注 protected 和 default 的差异,结合 “同包非子类、不同包子类” 的场景测试。

8. 问题:Java 中的异常处理机制是怎样的?

我的回答

Java 中的异常处理机制大部分都是抛那个 throw。Try 就是尝试这个方法是否能成功,然后 catch 捕捉异常,然后 finally 不管怎么样,它最终都会执行。

标准答案

  • 核心机制:通过try-catch-finally-throw-throws实现异常的捕获、处理和抛出,避免程序崩溃。
  • 关键组件:
    1. try:包裹可能抛出异常的代码块;
    2. catch:捕获指定类型的异常并处理(可多个 catch,按异常子类→父类顺序);
    3. finally:无论是否抛异常,都会执行(常用于释放资源,如关闭流、连接);
    4. throw:手动抛出异常(如throw new NullPointerException("空指针"));
    5. throws:声明方法可能抛出的异常(编译时异常必须声明)。
  • 异常分类:
    1. 编译时异常(Checked):编译时必须处理(捕获或声明),如IOExceptionSQLException
    2. 运行时异常(Unchecked):编译时不强制处理,运行时触发,如NullPointerExceptionArrayIndexOutOfBoundsException

指导

  • 不足:未提及throw(手动抛异常)、throws(声明异常);对异常分类及示例不熟悉。
  • 改进:结合 “读取文件” 的示例(try-catch-finally 关闭流),记忆异常处理流程;记 3 个常见编译时异常和 3 个运行时异常。

9. 问题:常见的异常类型,比如运行时异常和编译时异常的区别?

我的回答

运行时异常是要运行了才能异常,编译时异常是说在 IDE 上会提示的异常。

标准答案

维度编译时异常(Checked)运行时异常(Unchecked)
编译阶段强制处理(不处理报错)不强制处理
继承关系继承Exception(非RuntimeException继承RuntimeException
常见示例IOExceptionSQLExceptionClassNotFoundExceptionNullPointerExceptionArrayIndexOutOfBoundsExceptionArithmeticException(除数为 0)
产生原因外部环境问题(如文件不存在、数据库连接失败)代码逻辑错误(如空指针、数组越界)

指导

  • 不足:仅描述现象,未说明继承关系、产生原因及具体示例。
  • 改进:通过 “文件不存在→IOException(编译时)” 和 “调用 null 对象方法→NullPointerException(运行时)” 的场景,记忆两者差异。

10. 问题:Java 中的接口和抽象类有什么区别?

我的回答

抽象类跟接口,抽象类其实就是有普通方法和成员变量,接口是抽象方法和常量。如果是继承抽象类的话,要实现它的所有方法,如果是实现接口...(未说完)

标准答案

维度抽象类(abstract class)接口(interface)
定义关键字abstract classinterface
构造方法有(不能实例化,供子类调用)
方法类型可包含普通方法、抽象方法(abstract 修饰)JDK8 前:仅抽象方法;JDK8 后:可加默认方法(default)、静态方法
成员变量可包含任意访问修饰符的变量仅 public static final 常量(可省略修饰符)
继承 / 实现子类用 extends 继承,单继承类用 implements 实现,多实现
核心作用代码复用(封装共性方法 / 属性)定义行为规范(强制实现类遵守)

指导

  • 不足:未提及构造方法差异、继承 / 实现数量限制(单继承 vs 多实现)、JDK8 接口的默认方法;对核心作用理解不深。
  • 改进:用 “抽象类 Animal(含普通方法 eat ())、接口 Flyable(含抽象方法 fly ())” 示例,理解 “复用” vs “规范” 的核心差异。

11. 问题:Java 中 final 关键字的作用?

我的回答

Final 关键字就是不能继承,假如用在常量上面就不可更改,用在方法上面,就是最终方法也不能改,也不能重写。如果用在类上面,它就是不能被继承。总之 final 是最终方法。

标准答案

  • 修饰类:类不能被继承(如String类),子类无法 extends;
  • 修饰方法:方法不能被重写,可避免子类修改核心逻辑;
  • 修饰变量:
    1. 基本类型:值不可变(如final int a=10; a=20;报错);
    2. 引用类型:引用地址不可变(对象内容可改,如final User u=new User(); u.setName("张三");合法,u=new User();报错);
  • 关键特性:可重入性(修饰方法时,同一线程可多次调用,不会死锁)。

指导

  • 不足:未区分 “基本类型变量” 和 “引用类型变量” 的 final 差异;未提及 final 的可重入性。
  • 改进:重点记忆 “final 修饰引用→地址不变” 的核心,用 “final User u=new User ();” 示例理解对象内容可修改的特性。

12. 问题:Java 里 == 和 equals 的区别?

我的回答

等于(==)是比较它的对象地址,equals 的话是可以重写,比较它的值。

标准答案

  • ==:
    1. 基本数据类型:比较值是否相等(如int a=10; int b=10; a==b→true);
    2. 引用数据类型:比较对象的内存地址是否相等(是否为同一对象);
  • equals:
    1. 默认实现(Object 类):return this==obj;,本质是比较地址;
    2. 重写后(如 String、Integer):比较对象的内容是否相等(如String s1="abc"; String s2=new String("abc"); s1.equals(s2)→trues1==s2→false);
  • 示例:

    java

    运行

    Integer a=127; Integer b=127; a==b→true(缓存池);
    Integer c=128; Integer d=128; a==b→false(新对象);
    c.equals(d)→true(比较值)。
    

指导

  • 不足:未说明 == 对基本类型和引用类型的差异;未提及 equals 的默认实现。
  • 改进:用 “String 的 == 和 equals 对比”“Integer 缓存池示例” 强化记忆,核心是 “== 看地址,equals 看重写逻辑”。

13. 问题:Java 里的异常体系,包括 Checked 异常和 Unchecked 异常的区别,还有常见的异常类举例?

我的回答

受检异常跟非受检异常的区别就是编译时会检查,如果编译异常的话,编译期就会报错。运行异常只有运行时期才会报错,异常通常用 try catch finally 来处理。try 是用来尝试方法,catch 捕捉异常,finally 不管最终怎么样,它都会执行。

标准答案

  • 异常体系顶层:Throwable,分为Error(错误,如OutOfMemoryError,程序无法处理)和Exception(异常,可处理);
  • Checked 异常(受检):
    • 继承Exception,非RuntimeException
    • 编译时强制处理(捕获或声明throws);
    • 常见示例:IOException(文件读写)、SQLException(数据库操作)、ClassNotFoundException(类未找到);
  • Unchecked 异常(非受检):
    • 继承RuntimeException
    • 编译时不强制处理,运行时触发;
    • 常见示例:NullPointerException(空指针)、ArrayIndexOutOfBoundsException(数组越界)、ArithmeticException(除数为 0)、IllegalArgumentException(参数非法);
  • 处理原则:Checked 异常必须处理,Unchecked 异常需通过代码逻辑避免(如判空避免空指针)。

指导

  • 不足:未区分ErrorException;常见异常类举例匮乏;未说明 Unchecked 异常的避免方式。
  • 改进:记 “Error 是致命错误,Exception 是可处理异常”;默写 3 个 Checked 和 4 个 Unchecked 异常的类名及场景。

14. 问题:Java 中 String、StringBuffer 和 StringBuilder 的区别?

我的回答

他们都是字符串,String 是最原始的字面值,是不可更改的。通常从常量池里面取,然后 StringBuffer 和 StringBuilder 都是有缓冲,按效率来说,String 的效率最低,其次是 StringBuilder,StringBuffer 效率最高。❌

标准答案

类型不可变性线程安全底层实现效率核心场景
String不可变安全字符数组(final char [])字符串常量、少量拼接
StringBuffer可变安全(synchronized 修饰方法)字符数组多线程频繁拼接(如日志输出)
StringBuilder可变不安全字符数组单线程频繁拼接(如业务逻辑处理)
  • 关键:String 不可变→拼接时创建新对象(如a+b等价于new StringBuilder(a).append(b).toString()),效率低;后两者可变,直接扩容字符数组,效率高。

指导

  • 易错点:记反 StringBuffer 和 StringBuilder 的效率(StringBuffer 因同步锁效率低于 StringBuilder)。
  • 改进:用 “多线程用 StringBuffer,单线程用 StringBuilder,常量用 String” 的口诀记忆,结合拼接 1000 次字符串的效率对比示例。

15. 问题:Java 里的线程池,说说它的核心参数有哪些,都是干嘛的?

我的回答

Java 里线程池作用基本上是为了资源复用,避免频繁连接关闭造成的性能浪费。然后它的参数主要有最大允许的连接量,释放量什么之类的。Java 的线程池可以用在 JDBC 之类的多线程连接中。

标准答案

  • 核心作用:控制并发线程数,减少线程创建 / 销毁的开销,避免资源耗尽;
  • 核心参数(ThreadPoolExecutor 的构造方法):
    1. corePoolSize:核心线程数,长期存活(除非设置 allowCoreThreadTimeOut);
    2. maximumPoolSize:最大线程数,线程池能创建的最多线程;
    3. keepAliveTime:非核心线程空闲存活时间,超时销毁;
    4. TimeUnit:keepAliveTime 的单位(如 TimeUnit.SECONDS);
    5. BlockingQueue:任务队列,存储等待执行的任务(如 ArrayBlockingQueue、LinkedBlockingQueue);
    6. ThreadFactory:创建线程的工厂(可自定义线程名称);
    7. RejectedExecutionHandler:拒绝策略(任务满时如何处理,如 AbortPolicy 直接抛异常);
  • 常见场景:Web 服务器处理 HTTP 请求、批量数据导入导出、定时任务(Quartz)。

指导

  • 不足:核心参数记忆不全(仅想到最大连接量);未说明参数之间的配合逻辑(如核心线程满→队列满→创建非核心线程→达最大线程→拒绝)。
  • 改进:画 “任务提交流程图” 辅助记忆参数作用,重点记住前 5 个核心参数,结合 “Tomcat 的线程池处理请求” 的场景理解。

16. 问题:JVM 的内存模型,说说栈、堆、方法区都存啥?

我的回答

栈里面放的方法,堆里面放的对象,方法区里面放的方法。 ❌

标准答案

  • 栈(线程私有)
    • 每个线程对应一个栈,每个方法调用对应一个栈帧;
    • 存储:局部变量(基本类型、引用类型的地址)、操作数栈、方法返回地址;
    • 特点:方法执行完栈帧销毁,内存自动释放;
  • 堆(线程共享)
    • 存储:所有 new 创建的对象(包括成员变量)、数组;
    • 特点:垃圾回收(GC)的主要区域,内存动态分配;
  • 方法区(线程共享,JDK8 后为元空间):
    • 存储:类的元数据(类结构、方法字节码)、常量池(字符串常量、静态常量)、静态变量(static 修饰)、运行时常量池;

指导

  • 不足:描述过于笼统,未明确栈存储 “局部变量”、方法区存储 “类元数据 + 静态变量 + 常量池” 的核心;
  • 改进:用 “User u=new User (); u.setName ("张三");” 示例:u 是栈中的引用,User 对象(含 name 成员变量)在堆中,User 类的字节码、static 变量在方法区。

17. 问题:Java 里的基本数据类型有哪些,各自占多少字节?

我的回答

整数型 int 4 个字节,long 8 个字节,浮点型 float 4 个字节,double 8 个字节,字符型 1 个字节,布尔值没有明确的字节规定。

标准答案

基本类型字节数备注
byte1整数型最小范围
short2中短整数
int4最常用整数类型
long8需加后缀 L
float4需加后缀 F
double8默认浮点类型
char2存储 Unicode 字符,如 'a'、' 中'
boolean未明确虚拟机实现为 1 位或 1 字节,仅 true/false

指导

  • 易错点:漏记 byte(1 字节)、short(2 字节);char 的字节数记为 1(实际 2 字节)。
  • 改进:制作 “类型 - 字节数” 对照表,每天花 1 分钟默写,重点关注 char 和 byte 的差异。

18. 问题:Java 里的反射机制是干嘛的,说说它的基本使用场景?

我的回答

Java 反射机制是用来反射方法,通过反射机制可以直接修改类的方法里面的数据,会破坏类的封装结构。反射机制一般是用在框架里面的。

标准答案

  • 定义:运行时获取类的信息(构造器、方法、字段)并操作这些组件的能力(无需知道类的编译期结构);
  • 核心作用
    1. 动态创建对象(如Class.forName("com.User").newInstance());
    2. 动态调用方法(如Method m = clazz.getMethod("say"); m.invoke(obj));
    3. 访问私有成员(如Field f = clazz.getDeclaredField("name"); f.setAccessible(true););
  • 基本步骤
    1. 获取 Class 对象(3 种方式):类名.class对象.getClass()Class.forName("全类名")
    2. 获取组件(构造器 / 方法 / 字段):getConstructor()getMethod()getField()
    3. 操作组件:newInstance()(创建对象)、invoke()(调用方法)、set()(修改字段);
  • 使用场景:框架底层(Spring 依赖注入、MyBatis 映射 SQL、JUnit 反射调用测试方法);
  • 注意:破坏封装性,性能略低(反射操作需解析字节码)。

指导

  • 不足:未说明反射的核心步骤、动态创建对象 / 调用方法的能力;仅知道框架使用,但不明确具体场景(如 Spring DI)。
  • 改进:结合 “Spring 通过反射创建 User 对象并注入属性” 的场景,记忆反射的 3 个步骤,重点理解 “运行时动态操作” 的核心。

19. 问题:Java 里的集合框架,说说 List 和 Set 的主要区别,还有常用的实现类?

我的回答

List 跟 Set 都是单列集合。List 是可重复的,Set 是不可重复的。List 采用的有 Redis,还有 link。Set 有 Redis set 跟 link set。它们共同的方法有增删改查。Set 其实是 map 的实现,hash code 改了什么,我也忘记了。

标准答案

  • 核心区别:| 维度 | List | Set ||--------------|-------------------------------|-------------------------------|| 元素重复性 | 允许重复元素 | 不允许重复元素(依赖 equals 和 hashCode) || 元素顺序 | 有序(插入顺序 = 遍历顺序) | 无序(HashSet)/ 有序(LinkedHashSet 按插入顺序) || 索引访问 | 支持索引访问(get (int index)) | 不支持索引访问 || 核心接口方法 | add (int index, E e)、get (int index) | 无索引相关方法,add (E e) 返回 boolean(是否添加成功) |
  • 常用实现类:
    1. List:
      • ArrayList:动态数组,查询快(索引访问),增删慢(数组扩容 / 移位);
      • LinkedList:双向链表,增删快(修改指针),查询慢(遍历);
    2. Set:
      • HashSet:基于 HashMap 实现(元素存 HashMap 的 key),无序、去重,效率高;
      • LinkedHashSet:继承 HashSet,底层加链表维护插入顺序,有序、去重;
      • TreeSet:基于红黑树实现,自然排序(如 Integer 升序),去重;

指导

  • 易错点:混淆 Redis(非 Java 集合)与 Java 集合实现类;不知道 Set 的去重依赖equals()hashCode()
  • 改进:先明确 “List = 有序可重复 + 索引”“Set = 无序不可重复 + 无索引” 的核心,再记忆实现类的底层结构(数组 / 链表 / HashMap / 红黑树)及优缺点。

20. 问题:Java 中类的加载过程,分为哪几个阶段?

我的回答

不会。

标准答案

类加载过程是 JVM 将.class 文件加载到内存并初始化的过程,共 5 个阶段:

  1. 加载(Loading):
    • 读取.class 文件(从磁盘、jar 包等),将字节流转换为方法区的运行时数据结构;
    • 生成 Class 对象(存于堆中),作为访问类元数据的入口;
  2. 验证(Verification):
    • 检查.class 文件的合法性(如字节码格式、语法规范),避免恶意代码;
  3. 准备(Preparation):
    • 为类的静态变量(static)分配内存(在方法区),并赋默认值(如 static int a=10→默认值 0);
    • 注意:不执行静态代码块,仅赋默认值;
  4. 解析(Resolution):
    • 将符号引用(如类名、方法名)转换为直接引用(内存地址);
  5. 初始化(Initialization):
    • 执行静态代码块(static {}),为静态变量赋最终初始值(如 a=10);
    • 触发时机:首次主动使用类(如 new 对象、调用静态方法、访问静态变量);

指导

  • 不足:完全不了解类加载的 5 个阶段,属于知识盲区;
  • 改进:按 “加载→验证→准备→解析→初始化” 的顺序记忆,重点记住 “准备阶段赋默认值,初始化阶段赋最终值” 的核心差异,用 “static int a=10” 的示例辅助。

21. 问题:Java 中 HashMap 的底层实现原理,JDK7 和 JDK8 有啥区别?

我的回答

HashMap 就是用数组列表实现,JDK7 跟 JDK8 的区别是 JDK8 的列表达到一定长度会转化成红黑树。通过 hash code 分配内存,数组位置重复了就添加到列表后面,如果列表大于 8 以后就变成红黑树,小于 6 的话红黑树会变成链表,这是 JDK8 以后的新特性。

标准答案

  • 核心原理:基于 “哈希表(数组 + 链表 / 红黑树)” 实现,通过 hash () 方法计算 key 的哈希值,确定元素在数组的位置(索引 = 哈希值 & 数组长度 - 1);
  • JDK7 vs JDK8 区别:| 维度 | JDK7 | JDK8 ||--------------|-------------------------------|-------------------------------|| 底层结构 | 数组 + 链表(拉链法) | 数组 + 链表 / 红黑树(链表长度≥8 且数组长度≥64→红黑树;≤6→链表) || hash 计算 | 多次扰动(9 次异或 + 移位) | 简化扰动(1 次异或 + 移位),效率更高 || 存储结构 | Entry 数组(key、value、next、hash) | Node 数组(继承 Entry,优化结构) || 插入方式 | 头插法(新元素插链表头部) | 尾插法(新元素插链表尾部),避免死循环 || 扩容机制 | 数组长度达阈值(负载因子 0.75)→扩容为 2 倍,重新哈希 | 同 JDK7,但红黑树扩容时会拆分为链表 |

指导

  • 不足:未提及负载因子(0.75)、数组长度为 2 的幂次、JDK7 头插法可能导致死循环、JDK8 的 hash 计算简化等细节;
  • 改进:重点记忆 “结构升级(链表→红黑树)、插入方式(头插→尾插)、hash 计算简化” 三个核心差异,理解 “红黑树提升查询效率(O (logn) vs 链表 O (n))” 的优势。

22. 问题:Java 中 synchronized 关键字的作用和实现原理?

我的回答

关键字作用是同步,保证线程安全,让共享资源在多线程访问时不会乱套。

标准答案

  • 核心作用:实现线程同步,保证同一时间只有一个线程访问被修饰的代码块 / 方法,解决多线程并发的数据一致性问题;
  • 修饰范围:
    1. 实例方法:锁为当前对象(this);
    2. 静态方法:锁为当前类的 Class 对象;
    3. 代码块:锁为括号内的对象(如synchronized (obj) {});
  • 实现原理:
    • 底层依赖 JVM 的 “监视器锁(Monitor)”,通过ACC_SYNCHRONIZED标志(方法级)或monitorenter/monitorexit指令(代码块级)实现;
    • 锁的升级过程(从低到高):无锁→偏向锁→轻量级锁→重量级锁(减少锁竞争开销);
  • 关键特性:可重入性(同一线程可多次获取同一把锁,避免死锁,如递归调用 synchronized 方法);

指导

  • 不足:未说明 synchronized 的修饰范围(实例方法 / 静态方法 / 代码块)、实现原理(Monitor 锁)、锁升级和可重入性;
  • 改进:结合 “多线程自增计数器” 示例理解同步作用,记忆 “修饰范围→锁对象” 的对应关系,重点了解 “可重入性” 和 “锁升级” 的核心特性。

23. 问题:Integer 的缓存池机制,比如 Integer a = 127; Integer b = 127; 和 a=128;b=128; 时,== 的结果为啥不一样?

我的回答

不会。

标准答案

  • 缓存池机制:Java 为节省内存,预先创建了-128~127范围内的 Integer 对象,存于缓存池(IntegerCache类);
  • 自动装箱逻辑:
    • Integer a = 127;时,触发自动装箱,底层调用Integer.valueOf(127),直接从缓存池获取对象,故a==b→true
    • Integer a = 128;时,128 超出缓存范围,Integer.valueOf(128)会创建新的 Integer 对象,故a==b→false
  • 核心代码(Integer.valueOf ()):

    java

    运行

    public static Integer valueOf(int i) {if (i >= IntegerCache.low && i <= IntegerCache.high)return IntegerCache.cache[i + (-IntegerCache.low)];return new Integer(i);
    }
    
  • 注意:缓存范围可通过 JVM 参数-XX:AutoBoxCacheMax=N调整上限(如调整为 255);

指导

  • 不足:完全不了解缓存池范围和自动装箱的底层逻辑;
  • 改进:记住 “-128~127” 的核心范围,通过 “== 比较地址,equals 比较值” 的逻辑,理解两次结果差异的原因,可手动运行代码验证。

24. 问题:Java 中接口的默认方法(default method)是怎么回事,解决了什么问题?

我的回答

Java default 就是 clone,解决什么问题不知道。

标准答案

  • 定义:JDK8 及以后,接口中可定义带方法体的默认方法(用default修饰),实现类可直接继承或重写;
  • 核心作用:解决接口演进的兼容性问题;
    • 问题:JDK8 前,接口新增抽象方法后,所有实现类都必须重写该方法,否则编译报错,导致老代码无法兼容;
    • 解决:新增默认方法时提供默认实现,实现类无需强制重写,直接使用默认逻辑,也可根据需求重写;
  • 示例:

    java

    运行

    interface MyInterface {default void say() {System.out.println("默认实现");}
    }
    class MyImpl implements MyInterface {// 可直接使用say(),也可重写
    }
    
  • 注意:若实现多个接口,且接口有同名默认方法,实现类必须重写该方法(避免冲突);

指导

  • 不足:完全误解默认方法的含义,不知道其 “解决接口演进兼容性” 的核心作用;
  • 改进:重点记忆 “默认方法 = 带方法体 + 解决接口新增方法兼容问题”,结合 “集合框架 List 接口新增 sort () 默认方法” 的实际场景理解。

25. 问题:Java 中 IO 流的分类,比如字节流和字符流的区别,还有常用的类?

我的回答

字节流是一个字节一个字节的传数据,通常用的是 BYTE writer 什么的方法,用来传输二进制数据,视频音乐什么的。字符流只能用来传输文本数据,还要注意编码,编码错会乱码,方法是 write 和 read。

标准答案

  • IO 流分类:
    1. 按处理数据类型:字节流(处理二进制数据)、字符流(处理文本数据,依赖编码);
    2. 按流向:输入流(读数据)、输出流(写数据);
  • 字节流与字符流区别:| 维度 | 字节流 | 字符流 ||--------------|-------------------------------|-------------------------------|| 处理数据 | 二进制数据(图片、视频、文件) | 文本数据(.txt、日志) || 依赖编码 | 不依赖(直接操作字节) | 依赖(字节→字符需编码,如 UTF-8) || 核心父类 | 输入:InputStream;输出:OutputStream | 输入:Reader;输出:Writer || 常用类 | FileInputStream、FileOutputStream、BufferedInputStream | FileReader、FileWriter、BufferedReader || 核心方法 | read ()(读字节)、write (int b)(写字节) | read ()(读字符)、write (int c)(写字符) |
  • 关键:字符流底层依赖字节流,缓冲流(BufferedXXX)通过缓存减少 IO 次数,提高效率;

指导

  • 不足:常用类记忆不准确(如字节流的 FileInputStream);未说明字符流依赖字节流的底层关系;
  • 改进:用 “表格 + 场景” 记忆:二进制文件(图片)用 FileInputStream,文本文件用 FileReader+BufferedReader(按行读取readLine())。

总结指导

1. 整体改进方向

  • 避免 “笼统回答”:每个问题尽量分点、结合示例,比如讲多态时必须提 “父类引用指向子类对象” 和instanceof
  • 攻克 “知识盲区”:重点补全类加载过程、Integer 缓存池、接口默认方法、反射步骤等完全不会的知识点;
  • 强化 “细节记忆”:基本数据类型的字节数 / 取值范围、访问修饰符表格、StringBuffer 与 StringBuilder 的效率差异等,用 “表格 + 口诀” 辅助;
  • 关联 “场景与原理”:每个知识点结合实际场景(如 HashMap 用在缓存、线程池用在 Web 请求),理解底层逻辑(如 HashMap 的红黑树提升查询效率)。

2. 复习方法建议

  • 每日默写:每天花 30 分钟默写核心表格(基本数据类型、访问修饰符、List/Set 区别、JDK7/8 HashMap 区别);
  • 代码验证:对模糊知识点(如 Integer 缓存池、== 和 equals 差异),手动写代码运行,直观感受结果;
  • 场景联想:看到框架(如 Spring),联想底层技术(反射、依赖注入);看到多线程,联想 synchronized、线程池;
  • 错题整理:将易错点(如 StringBuffer 和 StringBuilder 的效率)单独记录,反复强化。

通过以上针对性复习,可快速弥补细节漏洞和知识盲区,让 Java 基础回答更精准、全面,面试时更有竞争力。如果需要针对某个知识点深入讲解或补充更多面试题,可随时沟通!


压力🍐 还没开始背 回答的确实是一坨 大概知道怎么用 就是不知道怎么组织语言 和原理 定义啥的

http://www.dtcms.com/a/553520.html

相关文章:

  • AI优化亚马逊广告:DeepBI智能化托管让广告运营从负担变轻松,ACOS优化至23%以下
  • 关键词解释:梯度消失(Vanishing Gradient)与 梯度爆炸(Exploding Gradient)
  • 天津网站建设如何最近火爆的新闻
  • Maven内核探秘:从启动到构建全流程
  • CNCC 2025|开源AI基础设施论坛成功举办
  • 开源可信MCP,AICC机密计算新升级!
  • 混元图像3.0开源原生多模态生图新篇章
  • 环境搭建与第一个程序:Hello, Rust!
  • [论文阅读] AI | 大语言模型服务系统服务级目标和系统级指标优化研究
  • 帝国网站管理系统视频教程asp网站开发
  • 自己做的网站申请软著物联网是干嘛的
  • 企业形象破局指南——缺乏专业线上展示?官网SEO优化重构品牌信任
  • webgl 变换矩阵:旋转、平移、缩放
  • 怎么做婚介网站襄阳php网站开发
  • 网站建设规划书案例济南做网站互联网公司有哪些
  • float为什么会丢失精度?
  • 网站产品后台界面怎么做微信朋友圈广告推广
  • 香港科技大学广州|可持续能源与环境学域博士招生宣讲会—吉林大学专场
  • LaTeX 重点表格文字对不齐(有些列文字和其他列差一行才显示)的原因和解决办法
  • 网站推广必做百度云打开的wordpress
  • soular零基础学习,如何统一管理TikLab帐号体系
  • kanass零基础学习:创建第一个项目
  • 【C语言实战(66)】筑牢防线:C语言安全编码之输入与错误处理
  • 【机器学习11】决策树进阶、随机森林、XGBoost、模型对比
  • 唯品会 一家专门做特卖的网站做振动盘的企业网站
  • 我的WordPress网站锦州网站建设市场
  • Spring Boot 3.3新特性全解析
  • 剪映蒙版模糊去水印全攻略:静态/动态水印
  • PandaCoder 2.4.3 震撼发布!
  • LeetCode 分类刷题:445. 两数相加 II