Skip to main content

Java面试

Java基础与面向对象

  1. 面向对象的四大特性:封装、继承、多态、抽象
    • 封装: 数据(属性)和操作数据的方法(行为)绑定在一起,外部不能直接访问对象的内部数据,而是通过提供的公开方法(getter/setter)来访问
    • 继承: 子类继承父类的属性和方法,从而实现代码复用,子类是父类的特殊化,子类可以拥有父类的非私有成员
    • 多态: 作用于不同对象时表现不同的行为方式,一个接口多个实现
      • 编译时(方法重载): 同一个类中方法名相同、参数不同
      • 运行时(方法重写): 子类重写父类方法,调用时通过父类引用调用子类实现.
    • 抽象: 抽象是对现实世界事务本质特征的提取,隐藏实现细节,只暴露对外接口
      • 抽象类
      • 接口
  2. 接口 vs 抽象类区别及应用场景
    1. 接口
      1. 多个类需要实现相同能力
      2. 定义规范或能力
    2. 抽象类
      1. 父类具有通用属性或逻辑
      2. 子类具有is-a关系,并共享通用逻辑
  3. equals()与hashCode()的契约及重写方法

    在Java中,希望对象在集合中能正确比较和查找,就必须同时重写equals()和hascode()。equals()用于判断对象逻辑是否相等,而hashCode()保证哈希容器的一致性。他们之间有严格的契约:如果两个对象相等,他们的哈希值也必须相等。

Java线程

  1. 线程创建
    1. 继承Threadl类并重写run方法
      1. 简单易用,单继承限制灵活性
      2. 每个线程独立实例,资源消耗较高
    2. 实现Runnable接口并实现run方法
      1. 封装在Runnable实现类中,通过Thread类包装执行。避免单继承,支持多线程共享同一任务
      2. 推荐基础方式,适合无返回值场景
    3. 使用Callable接口配合FutureTask实现带返回值的线程
      import java.util.concurrent.*
      class MyCallable implements Callable<String>{
      @Override
      public String call() throws Exception{
      return "Callable result"
      }
      }
      // 使用FutureTask包装callable
      FutureTask<String> futureTask = new FutureTask<>(new MyCallable());
      Thread thread = new Thread(futureTask);
      thread.start();
      system.out.println(futuretask.get()); // 获取结果
      // 使用Executor线程池来提交
      ExecutorService executor = Executors.newSingleThreadExecutor();
      // 提交Callable任务
      Future<String> future = executor.submit(new MyCallable());
      System.out.println(future.get());
      executor.shudown(); // 关闭线程池
    4. 通过线程池(如Executor框架)创建管理线程
      1. 高线管理线程生命周期,避免频繁创建和销毁开销
      2. 支持任务队列、现成复用和资源控制
    5. 使用lambda表达式或匿名内部类简化线程实现
  2. wait()和sleep()区别
    1. 所属类不同: wait()来自于Object类,sleep()来自Thread类。
    2. 释放锁: wait()会释放对象锁,sleep()保持锁不放
    3. 使用条件: wait()必须在同步代码块中调用,sleep()没有限制
    4. 唤醒机制: wait()需notify()唤醒,sleep()超时自动恢复或中断
    5. 应用场景: wait()用于线程协作,sleep()用于暂停执行.
  3. 线程同步方式
    1. 基本同步方式
      1. synchronized关键字(最常用): 修饰方法或代码块,保证同一时间只有一个线程可以访问
        public synchronized void increment() {
        count++;
        }
        public void increment(){
        synchronized(this){
        count++;
        }
        }
      2. ReentrantLock(显式锁)
        // 比synchronized更灵活(支持超时、可中断、读写锁等)
        Lock lock = new ReentrantLock();
        lock.lock();
        try {
        count++;
        } finally {
        lock.unlock();
        }
    2. 通信协调工具
      1. volatile
        1. 保证可见性(不保证原子性)
        2. 多用于状态标记(如终止线程)
      2. wait()/notify()/notifyAll()(Object类)
        1. 多线程通信使用,配合sychronized
    3. J.U.C工具类(更高层)
      1. CountDownLatch
        1. 等待多个线程完成某个动作在继续
          CountDownLatch latch = new CountDownLatch(3);
          new Thread(()->{
          // do task
          latch.countDwon();
          }).start
          latch.await(); // 主线程等3个子线程
      2. CyclicBarrier
        1. 所有线程到达屏障点后再继续执行
        2. CyclicBarrier barrier = new CyclicBarrier(3, () -> System.out.println("全部到达"));
      3. Semaphore
        1. 限制并发数量
            Semaphore semaphore = new Semaphore(5);
          semaphore.acquire();
          try {
          // access resource
          } finally {
          semaphore.release();
          }
      4. ReadWriteLock
        1. 多线程读,单线程写(如缓存场景)
          ReadWriteLock rwLock = new ReentrantReadWriteLock();
          rwLock.readLock().lock();
  4. AQS(AbstractQueuedSynchronizer)
    1. 状态管理
    2. 等待队列(CLH变种队列)
      1. 双向链表结构: 队列中的每个节点(Node)代表一个等待线程,保证线程引用、等待状态(WAITING、CANCELLED等)及前驱/后继指针
      2. 自旋 + 阻塞: 线程在入队后先自旋尝试获取资源,失败后通过LockSupport.park()挂起,避免无意义的CPU占用.
    3. 模版方法模式
      1. 子类需实现的方法
        1. tryAcquire(int): 尝试独占式获取资源
        2. tryRelease(int): 尝试独占式释放资源.
        3. tryAcquireShared(int): 尝试共享式获取资源.
        4. tryReleaseShared(int): 尝试共享式释放资源
      2. AQS提供的核心方法:
        1. acquire(int): 获取资源(可能阻塞)
        2. release(int): 释放资源并唤醒后续线程

Spring内容:

  1. Springboot 常用注解
    1. 启动类注解:
      1. @SpringBootApplication(主启动类)
        1. @SpringBootConfiguration: 声明当前类是配置类(等价于@Configuration)
        2. @EnableAutoConfiguration: 开启自动配置(关键功能,让SpringBoot自动加载符合条件的Bean)
        3. @ComponentScan: 扫描当前包及子包下的@Component及其衍生注解(如@Service)标记的类,注册为Bean
      2. 依赖注入注解(IOC)注解
        1. @Component: 被IOC管理的类的基础注解
        2. @Service: 标记业务层(Service层)组件(等价于@Component,语义更明确)
        3. @Controller: Web控制器组件
        4. @Reposity: 标记访问层DAO层组件
        5. @Configuration: 标记配置类
        6. @Bean: 生命bean(标注在方法上,方法返回值会被注册到IOC容器)
      3. 配置管理注解
        1. @Value
        2. @ConfigurationProperties: 批量绑定配置到Java对象
        3. @PropertySouce: 加载自定义配置文件
        4. @EnableConfigurationProperties: 启用@ConfigurationProperties标记的类(通用配合@Configuration使用)
  2. Springboot的启动流程
        mian方法

    SpringApplication.run()

    准备环境(加载环境、激活Profile等)

    创建上下文(根据应用类型(web/非web)实例化对应ApplicationContext)

    自动配置(通过EnableAutoConfiguration加载并过滤自动配置类,注册Bean,注解扫描等)

    刷新ApplicationContext(实例化Bean,注入依赖,启动内置web服务器)

    调用 ApplicationRunner / CommandLineRunner

    success
  3. Bean的生命周期
        实例化Bean

    属性注入(Autowired,value,Resource)

    调用xxxAware接口注入上下文

    调用@PostConstruct注解初始化逻辑

    InitializingBean.afterPropertiesSet

    自定义 init-method初始化方法

    BeanPostProcessor.beforeInit(Bean初始化前执行的操作比如AOP、日志等)

    BeanPostProcessor.afterInit

    Bean准备就绪

    容器销毁、关闭(@PreDestory)
  4. IOC
    1. 控制反转(IOC)
      • 对象主动创建依赖对象,IOC将对象的创建权交给容易,对象被动接收依赖
      • 实现方式:
        • 依赖注入(DI): 通过构造器、Setter方法或字段注入依赖.
        • 依赖查找(DL): 通过接口主动查询依赖(如EJB的JNDI),但Spring主要采用DI
    2. IOC容器作用:
      1. 管理Bean的生命周期:实例化、初始化、销毁
      2. 依赖装配: 解析Bean间的依赖关系并注入
      3. 配置隔离: 通过XML、注解或Java配置类定义Bean,与业务代码解耦
    3. 实现方式:
      1. 构造器注入
      2. Setter方法注入
  5. AOP实现 AOP(面相切面编程)通过横向抽取公共功能(如日志、事务),解决代码重复和解耦问题。以动态代理机制在目标方法织入增强逻辑\
    1. 核心概念
      1. 横向关注点(Cross-cutting Concerns): 分散在多个模块中的公共功能(如日志、事务)
      2. 切面(Aspect): 封装横切逻辑的模块(通过@Aspect注解定义)
      3. 连接点(Join Point): 程序执行过程中的某个点(如方法调用、异常抛出)
      4. 切点(Pointcut): 通过表达式匹配需要增强的连接点(@Pointcut("execution(com.example..*(..))"))
      5. 通知(Advice): 在切点执行的增强逻辑,分为:
        1. @Before: 方法执行前
        2. @AfterReturning: 方法正常返回之后
        3. @AfterThrowing: 方法抛出异常后.
        4. @After(Finally): 方法执行后(无论成功或异常)
        5. @Around: 环绕通知(可控制方法执行流程)
    2. 如何引入
      1. 引入AOP依赖
      2. 定义切面类(@Aspect和@Component)
      3. 目标方法
  6. @Autowired和@Resource
    1. @Autowired:
      1. Spring框架自定义的注解
      2. 按类型匹配
      3. 构造方法(推荐,显式依赖)、字段、方法、参数上.
      4. 依赖必须存在(required=true),否则启动时排除NoSuchBeanDefinitionException
    2. @Resource
      1. JSR-250的DI容器
      2. 默认按照名称匹配
      3. 用于字段和setter方法,不支持构造方法和参数注入
      4. 不支持@Primary、Lazy注解直接配合
  7. Spring事务
    1. 编程式事务
      1. 基于PlatFormTransactionManager接口(底层接口)实现
    2. 声明式事务: 通过AOP(面向切面编程)自动管理事务,事务控制逻辑与业务代码解耦
      1. 作用范围: 可标注在类(所有方法生效)或方法(仅当前方法生效)上
      2. 常用属性:
        1. propagation: 事务传播行为(默认REQUIRED)
        2. isolation: 事务隔离级别(默认DEFAULT, 使用数据库默认)
        3. rollbackFor: 指定需要回滚的异常类型(默认仅回滚RuntimeException和Error)
        4. readOnly: 标记事务为只读(优化数据库性能)
        5. timeout: 事务超时时间(秒)
  8. Spring MVC执行流程
    1. 流程
      1. 用户请求有DispatcherServlet统一接收处理
      2. HandlerMapping根据URL映射找到对应的Controller方法
      3. HandlerAdapter调用Controller处理业务逻辑,返回ModelAndView
      4. ViewResolver解析视图名称,定位具体视图模版
      5. 视图引擎渲染数据,生成响应返回客户端
    2. 示例:
      1. 用户访问user/1
      2. DispatcherServlet接收请求,通过HandlerMapping找到UserControoler.getUser方法
      3. HandlerAdapter解析参数,调用getUser(1)
      4. UserService查询用户数据,返回User对象.
      5. HandlerAdapter将User对象通过HttpMesasageConverter转为Json
      6. DispatcherServlet返回Json给用户
  9. @Component和@Bean的区别是什么
    1. 区别:
      1. @Component: 适合"自动注册"自定义的业务类,Spring自动扫描并管理生命周期,开发者无需干预创建过程
        1. 类级注解,标记在一个Java类上,Spring会自动扫描
        2. Spring自动完成实例化
        3. 颗粒度对Bean的控制较为有限,仅能通过注解(如@Scope、@Lazy)或生命周期注解(@PostConstruct、@PreDestory)调整行为.
      2. @Bean: 适合"手动注册"需要个性化控制的Bean(如第三方类、复杂初始化逻辑),通过方法灵活定义创建过程
        1. 方法级注解,标记在一个方法上(通常在@Configuration标记的配置类中).通过该方法返回值项容器注册一个Bean.
        2. 手动实例化逻辑
  10. SpringSecurity
    1. 核心功能:
      1. 身份验证(Authentication)
        1. 验证用户身份(用户名/密码、OAuth2 Token、JWT等)
        2. 支持多种认证方式:表单登录、HTTP Basic认证、LDAP、CAS、OAuth2
      2. 授权(Authorization)
        1. 控制用户访问资源的权限(如何角色、权限列表等)
        2. 支持基于URL、方法注解、表达式(SpEL)的细粒度权限控制
      3. 攻击防护
        1. CSRF: 防止跨站请求
        2. 会话管理: 防止会话固定攻击,支持会话超时和并发控制
        3. 安全头部: 自动添加XSS防护、CORS控制等HTTP安全头
      4. 密码安全
        1. 内置密码加密工具
        2. 支持密码哈希算法升级和旧密码兼容
    2. 核心组件
      1. Filter Chain(过滤器链) Spring Security通过一组过滤器拦截请求,按顺序执行安全逻辑:
        1. UsernamePasswordAuthenticationFilter: 处理表单登录
        2. BasicAuthenticationFilter: 处理HTTP Basic认证
        3. JwtAuthenticationFilter: 自定义JWT Token解析
        4. ExceptionTranslationFilter: 处理安全异常(如未认证、权限不足)
      2. Authentication Manager
        1. 身份验证的核心入口,负责验证用户凭据(如DaoAuthenticationProvider结合数据库查询)
      3. Access Control(访问控制)
        1. URL级别: 通过http.authorizeRequests()配置资源访问权限
        2. 方法级别: 使用@PreAuthorize("hasRole('ADMIN')")注解控制方法访问
        3. SpEL: 动态判断权限(如haslpAddress('192.168.1.0/24'))

Springboot


  1. springboot 启动流程
            [main 方法]


    ┌────────────────────────────┐
    │ SpringApplication.run() │
    └────────────────────────────┘


    ┌────────────────────────────┐
    │ 创建 SpringApplication 对象 │
    └────────────────────────────┘


    ┌────────────────────────────┐
    │ 推断项目类型、主类、加载器 │
    └────────────────────────────┘


    ┌────────────────────────────┐
    │ prepareEnvironment() │ ← 加载配置文件、系统环境、命令行参数
    └────────────────────────────┘


    ┌────────────────────────────┐
    │ 创建 ApplicationContext │ ← 创建 IoC 容器
    └────────────────────────────┘


    ┌────────────────────────────┐
    │ applyInitializers() │ ← 执行初始化器
    └────────────────────────────┘


    ┌────────────────────────────┐
    │ refreshContext() │ ← 扫描/注册 Bean,依赖注入
    └────────────────────────────┘


    ┌────────────────────────────┐
    │ 启动内嵌 Web 服务器(Tomcat) │
    └────────────────────────────┘


    ┌────────────────────────────┐
    │ 执行 CommandLineRunner 等 │
    └────────────────────────────┘


    ┌────────────────────────────┐
    │ Spring Boot 启动完成 │
    └────────────────────────────┘