北京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 天只更新核心面试题 ~

相关推荐
烧冻鸡翅QAQ4 分钟前
从0开始的游戏编程——开发前的编程语言准备(JAVAScript)
开发语言·javascript·游戏
saber_andlibert9 分钟前
【C++转GO】文件操作+协程和管道
开发语言·c++·golang
苏叶新城15 分钟前
SpringBoot 3.5 JPA投影
java·spring boot·后端
Vic1010121 分钟前
Spring AOP 常用注解完全指南
java·后端·spring
Halo_tjn21 分钟前
Java IO流实现文件操作知识点
java·开发语言·windows·算法
FL162386312927 分钟前
VTK源码编译时候选qt5路径
开发语言·qt
Felven28 分钟前
C. Maximum Median
c语言·开发语言·算法
白兰地空瓶39 分钟前
告别 add(1, 2)!通过 JS 柯里化,让你的代码更加优雅
javascript·面试
CryptoRzz41 分钟前
StockTV API 对接全攻略(股票、期货、IPO)
java·javascript·git·web3·区块链·github
iReachers1 小时前
为什么HTML打包安卓APP安装时会覆盖或者报错?
android·java·html·html打包apk·网页打包