北京JAVA基础面试30天打卡01

希望大家坚持下去,30 天只更新核心面试题 ~

1. 接口和抽象类的区别

特性 接口 (Interface) 抽象类 (Abstract Class)
定义 使用 interface 关键字定义,JDK 8 起支持默认方法和静态方法。 使用 abstract class 关键字定义,包含抽象方法或具体方法。
继承 类可以实现多个接口(多实现)。 类只能继承一个抽象类(单继承)。
成员变量 只能定义 public static final 的常量(默认)。 可以定义任意类型的成员变量(包括实例变量)。
方法 JDK 8 前只能有抽象方法;JDK 8 起支持默认方法和静态方法。 可以有抽象方法和具体方法。
构造方法 没有构造方法。 可以有构造方法,供子类调用。
访问修饰符 方法默认 public,无法定义 protected 或 private 方法。 方法和变量可以有任意访问修饰符。
使用场景 定义行为规范,强调契约式编程,适合松耦合设计。 提供部分实现,适合具有共同逻辑的类层次结构。

总结

  • 接口适合定义规范,强调"做什么",支持多实现,灵活性高。 自上而下,规定行为。
  • 抽象类适合代码复用,强调"是什么",提供部分实现,适合有共同行为的类。 自下而上,抽取共性,一般重构用。
    其他:
    Java8:引l入了default和static方法,使得接口不仅仅
    是方法的声明,还可以提供具体的实现。default方法允
    许在接口中添加新的方法实现,而不影响己经实现该接口
    的类。
    Java9:引l入了私有方法,允许在接口中定义私有方法,
    用于default方法的内部逻辑复用。
    Java 14:引l入了sealed接口(仅在某些子类中使用),
    进一步增强了接口的功能

2. JDK 动态代理和 CGLIB 动态代理的区别

特性 JDK 动态代理 CGLIB 动态代理
实现方式 基于接口,使用 Java 的 java.lang.reflect.Proxy 类。 基于继承,使用 ASM 字节码操作框架生成子类。
依赖 目标类必须实现接口。 目标类无需实现接口,但不能是 final 类或方法。
代理对象生成 通过反射生成实现接口的代理类。 通过字节码生成目标类的子类。
性能 性能稍低(依赖反射调用)。 性能较高(直接字节码操作,调用效率接近原生)。
使用场景 Spring 默认使用,AOP 中目标类有接口时优先选择。 Spring AOP 中目标类无接口时使用,或需要代理非接口方法。
方法调用 通过 InvocationHandler 的 invoke 方法拦截。 通过 MethodInterceptor 的 intercept 方法拦截。
局限性 只能代理接口定义的方法,无法代理非接口方法。 无法代理 final 类或 final 方法。

总结

  • JDK 动态代理:适合有接口的场景,代码简单,依赖 JDK 原生支持,但性能稍逊。
  • CGLIB 动态代理:适合无接口的场景,性能更高,但依赖第三方库(如 ASM),对 final 类无能为力。
  • Spring 中的选择 :Spring AOP 默认使用 JDK 动态代理,若目标类无接口则自动切换到 CGLIB。
    其他
    1.jdk6 下,在运行次数较少的情况下,jdk动态代理与
    cglib差距不明显,甚至更快一些;而当调用次数增加
    之后,cglib表现稍微更快一些
    2.jdk7 下,情况发生了逆转!在运行次数较少
    (1,000,000)的情况下,jdk动态代理比cglib快了差
    不多30%;而当调用次数增加之后(50,000,000),动
    态代理比cglib快了接近1倍
    3.jdk8表现和jdk7基本一致

3. Java 的反射机制及其应用

什么是反射? Java 反射机制允许程序在运行时动态获取类的元信息(如类名、方法、字段、构造器等)并操作这些信息。核心类位于 java.lang.reflect 包,如 Class、Method、Field、Constructor。

如何应用反射?

  1. 获取 Class 对象

    java 复制代码
    // 三种方式
    
    Class<?> clazz1 = Class.forName("java.util.ArrayList");
    
    Class<?> clazz2 = ArrayList.class;
    
    Class<?> clazz3 = new ArrayList<>().getClass();
  2. 操作构造器

    java 复制代码
    Constructor<?> constructor = clazz1.getDeclaredConstructor();
    
    constructor.setAccessible(true); // 绕过访问限制
    
    Object instance = constructor.newInstance(); // 创建实例
  3. 操作方法

    java 复制代码
    Method method = clazz1.getDeclaredMethod("add", Object.class);
    
    method.setAccessible(true);
    
    method.invoke(instance, "test"); // 调用方法
  4. 操作字段

    java 复制代码
    Field field = clazz1.getDeclaredField("elementData");
    
    field.setAccessible(true);
    
    Object value = field.get(instance); // 获取字段值

应用场景

  • 框架开发:如 Spring(通过反射实例化 Bean)、Hibernate(动态映射实体类字段)。
  • 动态代理:JDK 动态代理依赖反射实现方法调用。
  • 序列化/反序列化:如 JSON 库(FastJSON、Gson)通过反射读写对象字段。
  • 工具类:如单元测试框架(JUnit)通过反射调用测试方法。
  • 插件化开发:动态加载未知的类或方法。

优缺点

  • 优点:灵活性高,支持运行时动态操作,适合框架和通用工具开发。
  • 缺点
    • 性能开销大(反射调用比直接调用慢)。
    • 安全性问题(绕过访问限制可能导致不可预期的行为)。
    • 代码可读性差,维护成本高。

注意事项

  • 尽量缓存 Class、Method 等对象以减少反射开销。
  • 谨慎使用 setAccessible(true),可能引发安全漏洞。
  • 在高性能场景下,优先考虑非反射方案(如字节码操作或直接调用)。

总结**:

  • 接口和抽象类在继承、方法实现和使用场景上各有侧重,接口更灵活,抽象类更适合复用。
  • JDK 动态代理依赖接口,CGLIB 基于继承,Spring 根据目标类情况自动选择
  • 反射机制是 Java 动态性的核心,广泛应用于框架开发,但需注意性能和安全问题

希望大家坚持下去,30 天只更新核心面试题 ~

相关推荐
拉不动的猪20 分钟前
回顾 pinia VS vuex
前端·vue.js·面试
Noii.21 分钟前
Mybatis的应用及部分特性
java·数据库·mybatis
Warren9825 分钟前
Java异常讲解
java·开发语言·前端·javascript·vue.js·ecmascript·es6
阿巴~阿巴~43 分钟前
面向对象编程基础:类的实例化与对象内存模型详解
开发语言·c++
JIngJaneIL1 小时前
家常菜点餐|基于java和小程序的家庭大厨家常菜点餐系统设计与实现(源码+数据库+文档)
java·数据库·小程序·vue·论文·毕设·家常菜点餐系统
熊猫片沃子1 小时前
Mybatis中进行批量修改的方法
java·后端·mybatis
设计师小聂!1 小时前
力扣热题100-------169.多数元素
java·数据结构·算法·leetcode·多数元素
拉不动的猪1 小时前
jS篇Async await实现同步效果的原理
前端·javascript·面试
一只叫煤球的猫2 小时前
基于Redisson的高性能延迟队列架构设计与实现
java·redis·后端
WhyWhatHow2 小时前
JEnv:新一代Java环境管理器,让多版本Java管理变得简单高效
java·后端