Java面试
Java基础与面向对象
- 面向对象的四大特性:封装、继承、多态、抽象
- 封装: 数据(属性)和操作数据的方法(行为)绑定在一起,外部不能直接访问对象的内部数据,而是通过提供的公开方法(getter/setter)来访问
- 继承: 子类继承父类的属性和方法,从而实现代码复用,子类是父类的特殊化,子类可以拥有父类的非私有成员
- 多态: 作用于不同对象时表现不同的行为方式,一个接口多个实现
- 编译时(方法重载): 同一个类中方法名相同、参数不同
- 运行时(方法重写): 子类重写父类方法,调用时通过父类引用调用子类实现.
- 抽象: 抽象是对现实世界事务本质特征的提取,隐藏实现细节,只暴露对外接口
- 抽象类
- 接口
- 接口 vs 抽象类区别及应用场景
- 接口
- 多个类需要实现相同能力
- 定义规范或能力
- 抽象类
- 父类具有通用属性或逻辑
- 子类具有is-a关系,并共享通用逻辑
- 接口
-
equals()与hashCode()的契约及重写方法
在Java中,希望对象在集合中能正确比较和查找,就必须同时重写equals()和hascode()。equals()用于判断对象逻辑是否相等,而hashCode()保证哈希容器的一致性。他们之间有严格的契约:如果两个对象相等,他们的哈希值也必须相等。
Java线程
- 线程创建
- 继承Threadl类并重写run方法
- 简单易用,单继承限制灵活性
- 每个线程独立实例,资源消耗较高
- 实现Runnable接口并实现run方法
- 封装在Runnable实现类中,通过Thread类包装执行。避免单继承,支持多线程共享同一任务
- 推荐基础方式,适合无返回值场景
- 使用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(); // 关闭线程池 - 通过线程池(如Executor框架)创建管理线程
- 高线管理线程生命周期,避免频繁创建和销毁开销
- 支持任务队列、现成复用和资源控制
- 使用lambda表达式或匿名内部类简化线程实现
- 继承Threadl类并重写run方法
- wait()和sleep()区别
- 所属类不同: wait()来自于Object类,sleep()来自Thread类。
- 释放锁: wait()会释放对象锁,sleep()保持锁不放
- 使用条件: wait()必须在同步代码块中调用,sleep()没有限制
- 唤醒机制: wait()需notify()唤醒,sleep()超时自动恢复或中断
- 应用场景: wait()用于线程协作,sleep()用于暂停执行.
- 线程同步方式
- 基本同步方式
- synchronized关键字(最常用): 修饰方法或代码块,保证同一时间只有一个线程可以访问
public synchronized void increment() {
count++;
}
public void increment(){
synchronized(this){
count++;
}
} - ReentrantLock(显式锁)
// 比synchronized更灵活(支持超时、可中断、读写锁等)
Lock lock = new ReentrantLock();
lock.lock();
try {
count++;
} finally {
lock.unlock();
}
- synchronized关键字(最常用): 修饰方法或代码块,保证同一时间只有一个线程可以访问
- 通信协调工具
- volatile
- 保证可见性(不保证原子性)
- 多用于状态标记(如终止线程)
- wait()/notify()/notifyAll()(Object类)
- 多线程通信使用,配合sychronized
- volatile
- J.U.C工具类(更高层)
- CountDownLatch
- 等待多个线程完成某个动作在继续
CountDownLatch latch = new CountDownLatch(3);
new Thread(()->{
// do task
latch.countDwon();
}).start
latch.await(); // 主线程等3个子线程
- 等待多个线程完成某个动作在继续
- CyclicBarrier
- 所有线程到达屏障点后再继续执行
- CyclicBarrier barrier = new CyclicBarrier(3, () -> System.out.println("全部到达"));
- Semaphore
- 限制并发数量
Semaphore semaphore = new Semaphore(5);
semaphore.acquire();
try {
// access resource
} finally {
semaphore.release();
}
- 限制并发数量
- ReadWriteLock
- 多线程读,单线程写(如缓存场景)
ReadWriteLock rwLock = new ReentrantReadWriteLock();
rwLock.readLock().lock();
- 多线程读,单线程写(如缓存场景)
- CountDownLatch
- 基本同步方式
- AQS(AbstractQueuedSynchronizer)
- 状态管理
- 等待队列(CLH变种队列)
- 双向链表结构: 队列中的每个节点(Node)代表一个等待线程,保证线程引用、等待状态(WAITING、CANCELLED等)及前驱/后继指针
- 自旋 + 阻塞: 线程在入队后先自旋尝试获取资源,失败后通过LockSupport.park()挂起,避免无意义的CPU占用.
- 模版方法模式
- 子类需实现的方法
- tryAcquire(int): 尝试独占式获取资源
- tryRelease(int): 尝试独占式释放资源.
- tryAcquireShared(int): 尝试共享式获取资源.
- tryReleaseShared(int): 尝试共享式释放资源
- AQS提供的核心方法:
- acquire(int): 获取资源(可能阻塞)
- release(int): 释放资源并唤醒后续线程
- 子类需实现的方法
Spring内容:
- Springboot 常用注解
- 启动类注解:
- @SpringBootApplication(主启动类)
- @SpringBootConfiguration: 声明当前类是配置类(等价于@Configuration)
- @EnableAutoConfiguration: 开启自动配置(关键功能,让SpringBoot自动加载符合条件的Bean)
- @ComponentScan: 扫描当前包及子包下的@Component及其衍生注解(如@Service)标记的类,注册为Bean
- 依赖注入注解(IOC)注解
- @Component: 被IOC管理的类的基础注解
- @Service: 标记业务层(Service层)组件(等价于@Component,语义更明确)
- @Controller: Web控制器组件
- @Reposity: 标记访问层DAO层组件
- @Configuration: 标记配置类
- @Bean: 生命bean(标注在方法上,方法返回值会被注册到IOC容器)
- 配置管理注解
- @Value
- @ConfigurationProperties: 批量绑定配置到Java对象
- @PropertySouce: 加载自定义配置文件
- @EnableConfigurationProperties: 启用@ConfigurationProperties标记的类(通用配合@Configuration使用)
- @SpringBootApplication(主启动类)
- 启动类注解:
- Springboot的启动流程
mian方法
↓
SpringApplication.run()
↓
准备环境(加载环境、激活Profile等)
↓
创建上下文(根据应用类型(web/非web)实例化对应ApplicationContext)
↓
自动配置(通过EnableAutoConfiguration加载并过滤自动配置类,注册Bean,注解扫描等)
↓
刷新ApplicationContext(实例化Bean,注入依赖,启动内置web服务器)
↓
调用 ApplicationRunner / CommandLineRunner
↓
success - Bean的生命周期
实例化Bean
↓
属性注入(Autowired,value,Resource)
↓
调用xxxAware接口注入上下文
↓
调用@PostConstruct注解初始化逻辑
↓
InitializingBean.afterPropertiesSet
↓
自定义 init-method初始化方法
↓
BeanPostProcessor.beforeInit(Bean初始化前执行的操作比如AOP、日志等)
↓
BeanPostProcessor.afterInit
↓
Bean准备就绪
↓
容器销毁、关闭(@PreDestory) - IOC
- 控制反转(IOC)
- 对象主动创建依赖对象,IOC将对象的创建权交给容易,对象被动接收依赖
- 实现方式:
- 依赖注入(DI): 通过构造器、Setter方法或字段注入依赖.
- 依赖查找(DL): 通过接口主动查询依赖(如EJB的JNDI),但Spring主要采用DI
- IOC容器作用:
- 管理Bean的生命周期:实例化、初始化、销毁
- 依赖装配: 解析Bean间的依赖关系并注入
- 配置隔离: 通过XML、注解或Java配置类定义Bean,与业务代码解耦
- 实现方式:
- 构造器注入
- Setter方法注入
- 控制反转(IOC)
- AOP实现
AOP(面相切面编程)通过横向抽取公共功能(如日志、事务),解决代码重复和解耦问题。以动态代理机制在目标方法织入增强逻辑\
- 核心概念
- 横向关注点(Cross-cutting Concerns): 分散在多个模块中的公共功能(如日志、事务)
- 切面(Aspect): 封装横切逻辑的模块(通过@Aspect注解定义)
- 连接点(Join Point): 程序执行过程中的某个点(如方法调用、异常抛出)
- 切点(Pointcut): 通过表达式匹配需要增强的连接点(@Pointcut("execution(com.example..*(..))"))
- 通知(Advice): 在切点执行的增强逻辑,分为:
- @Before: 方法执行前
- @AfterReturning: 方法正常返回之后
- @AfterThrowing: 方法抛出异常后.
- @After(Finally): 方法执行后(无论成功或异常)
- @Around: 环绕通知(可控制方法执行流程)
- 如何引入
- 引入AOP依赖
- 定义切面类(@Aspect和@Component)
- 目标方法
- 核心概念
- @Autowired和@Resource
- @Autowired:
- Spring框架自定义的注解
- 按类型匹配
- 构造方法(推荐,显式依赖)、字段、方法、参数上.
- 依赖必须存在(required=true),否则启动时排除NoSuchBeanDefinitionException
- @Resource
- JSR-250的DI容器
- 默认按照名称匹配
- 用于字段和setter方法,不支持构造方法和参数注入
- 不支持@Primary、Lazy注解直接配合
- @Autowired:
- Spring事务
- 编程式事务
- 基于PlatFormTransactionManager接口(底层接口)实现
- 声明式事务: 通过AOP(面向切面编程)自动管理事务,事务控制逻辑与业务代码解耦
- 作用范围: 可标注在类(所有方法生效)或方法(仅当前方法生效)上
- 常用属性:
- propagation: 事务传播行为(默认REQUIRED)
- isolation: 事务隔离级别(默认DEFAULT, 使用数据库默认)
- rollbackFor: 指定需要回滚的异常类型(默认仅回滚RuntimeException和Error)
- readOnly: 标记事务为只读(优化数据库性能)
- timeout: 事务超时时间(秒)
- 编程式事务
- Spring MVC执行流程
- 流程
- 用户请求有DispatcherServlet统一接收处理
- HandlerMapping根据URL映射找到对应的Controller方法
- HandlerAdapter调用Controller处理业务逻辑,返回ModelAndView
- ViewResolver解析视图名称,定位具体视图模版
- 视图引擎渲染数据,生成响应返回客户端
- 示例:
- 用户访问user/1
- DispatcherServlet接收请求,通过HandlerMapping找到UserControoler.getUser方法
- HandlerAdapter解析参数,调用getUser(1)
- UserService查询用户数据,返回User对象.
- HandlerAdapter将User对象通过HttpMesasageConverter转为Json
- DispatcherServlet返回Json给用户
- 流程
- @Component和@Bean的区别是什么
- 区别:
- @Component: 适合"自动注册"自定义的业务类,Spring自动扫描并管理生命周期,开发者无需干预创建过程
- 类级注解,标记在一个Java类上,Spring会自动扫描
- Spring自动完成实例化
- 颗粒度对Bean的控制较为有限,仅能通过注解(如@Scope、@Lazy)或生命周期注解(@PostConstruct、@PreDestory)调整行为.
- @Bean: 适合"手动注册"需要个性化控制的Bean(如第三方类、复杂初始化逻辑),通过方法灵活定义创建过程
- 方法级注解,标记在一个方法上(通常在@Configuration标记的配置类中).通过该方法返回值项容器注册一个Bean.
- 手动实例化逻辑
- @Component: 适合"自动注册"自定义的业务类,Spring自动扫描并管理生命周期,开发者无需干预创建过程
- 区别:
- SpringSecurity
- 核心功能:
- 身份验证(Authentication)
- 验证用户身份(用户名/密码、OAuth2 Token、JWT等)
- 支持多种认证方式:表单登录、HTTP Basic认证、LDAP、CAS、OAuth2
- 授权(Authorization)
- 控制用户访问资源的权限(如何角色、权限列表等)
- 支持基于URL、方法注解、表达式(SpEL)的细粒度权限控制
- 攻击防护
- CSRF: 防止跨站请求
- 会话管理: 防止会话固定攻击,支持会话超时和并发控制
- 安全头部: 自动添加XSS防护、CORS控制等HTTP安全头
- 密码安全
- 内置密码加密工具
- 支持密码哈希算法升级和旧密码兼容
- 身份验证(Authentication)
- 核心组件
- Filter Chain(过滤器链) Spring Security通过一组过滤器拦截请求,按顺序执行安全逻辑:
- UsernamePasswordAuthenticationFilter: 处理表单登录
- BasicAuthenticationFilter: 处理HTTP Basic认证
- JwtAuthenticationFilter: 自定义JWT Token解析
- ExceptionTranslationFilter: 处理安全异常(如未认证、权限不足)
- Authentication Manager
- 身份验证的核心入口,负责验证用户凭据(如DaoAuthenticationProvider结合数据库查询)
- Access Control(访问控制)
- URL级别: 通过http.authorizeRequests()配置资源访问权限
- 方法级别: 使用@PreAuthorize("hasRole('ADMIN')")注解控制方法访问
- SpEL: 动态判断权限(如haslpAddress('192.168.1.0/24'))
- Filter Chain(过滤器链) Spring Security通过一组过滤器拦截请求,按顺序执行安全逻辑:
- 核心功能:
Springboot
- springboot 启动流程
[main 方法]
│
▼
┌────────────────────────────┐
│ SpringApplication.run() │
└────────────────────────────┘
│
▼
┌────────────────────────────┐
│ 创建 SpringApplication 对象 │
└────────────────────────────┘
│
▼
┌────────────────────────────┐
│ 推断项目类型、主类、加载器 │
└────────────────────────────┘
│
▼
┌────────────────────────────┐
│ prepareEnvironment() │ ← 加载配置文件、系统环境、命令行参数
└────────────────────────────┘
│
▼
┌────────────────────────────┐
│ 创建 ApplicationContext │ ← 创建 IoC 容器
└────────────────────────────┘
│
▼
┌────────────────────────────┐
│ applyInitializers() │ ← 执行初始化器
└────────────────────────────┘
│
▼
┌────────────────────────────┐
│ refreshContext() │ ← 扫描/注册 Bean,依赖注入
└────────────────────────────┘
│
▼
┌────────────────────────────┐
│ 启动内嵌 Web 服务器(Tomcat) │
└────────────────────────────┘
│
▼
┌────────────────────────────┐
│ 执行 CommandLineRunner 等 │
└────────────────────────────┘
│
▼
┌────────────────────────────┐
│ Spring Boot 启动完成 │
└────────────────────────────┘