校招Java面试常见知识点全解析(附实战案例)
一、Java新特性实战
1. Lambda表达式与Stream API
案例:统计电商订单中金额大于1000的订单数量
java
import java.util.Arrays;
import java.util.List;
public class LambdaStreamDemo {
public static void main(String[] args) {
List<Order> orders = Arrays.asList(
new Order(1, "20230601", 899.0),
new Order(2, "20230602", 1299.0),
new Order(3, "20230603", 1599.0),
new Order(4, "20230604", 699.0)
);
// 使用Stream API过滤并统计
long count = orders.stream()
.filter(order -> order.getAmount() > 1000)
.count();
System.out.println("金额大于1000的订单数量: " + count);
}
}
class Order {
private int id;
private String orderDate;
private double amount;
// 构造方法、Getter/Setter省略
}
面试考点:Lambda表达式语法、Stream的中间操作与终端操作、函数式接口
2. Optional类的使用
案例:处理可能为空的用户信息
java
import java.util.Optional;
public class OptionalDemo {
public static void main(String[] args) {
User user = null;
// 使用Optional避免空指针异常
Optional<User> optionalUser = Optional.ofNullable(user);
String username = optionalUser
.map(User::getUsername)
.orElse("Guest");
System.out.println("用户名: " + username);
}
}
class User {
private String username;
// 构造方法、Getter/Setter省略
}
面试考点:Optional的创建方式、常用方法(map/flatMap/filter/orElse/orElseThrow)
二、集合框架高级应用
1. List与Set的线程安全实现
案例:高并发场景下的商品ID集合处理
java
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;
public class ConcurrentCollectionDemo {
public static void main(String[] args) {
// 线程安全的List
CopyOnWriteArrayList<String> productIds = new CopyOnWriteArrayList<>();
// 线程安全的Set
CopyOnWriteArraySet<String> uniqueProductIds = new CopyOnWriteArraySet<>();
// 模拟多线程添加商品ID
Runnable task = () -> {
productIds.add("P" + System.currentTimeMillis());
uniqueProductIds.add("P" + System.currentTimeMillis());
};
// 启动10个线程
for (int i = 0; i < 10; i++) {
new Thread(task).start();
}
}
}
面试考点:CopyOnWrite容器的原理、适用场景及优缺点
2. Map的性能优化
案例:使用ConcurrentHashMap实现本地缓存
java
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
public class LocalCacheDemo {
private static final ConcurrentHashMap<String, CacheObject> cache = new ConcurrentHashMap<>();
public static void put(String key, Object value, long expireTime) {
cache.put(key, new CacheObject(value, System.currentTimeMillis() + expireTime));
}
public static Object get(String key) {
CacheObject cacheObject = cache.get(key);
if (cacheObject != null && System.currentTimeMillis() < cacheObject.getExpireTime()) {
return cacheObject.getValue();
}
return null;
}
static class CacheObject {
private Object value;
private long expireTime;
// 构造方法、Getter省略
}
}
面试考点:ConcurrentHashMap在JDK8中的优化、本地缓存的实现策略
三、多线程与并发编程
1. CompletableFuture异步编程
案例:电商订单的并行处理
java
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
public class CompletableFutureDemo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 异步处理订单支付
CompletableFuture<Boolean> paymentFuture = CompletableFuture.supplyAsync(() -> {
try {
// 模拟支付处理
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return true;
});
// 异步处理订单库存
CompletableFuture<Boolean> inventoryFuture = CompletableFuture.supplyAsync(() -> {
try {
// 模拟库存检查
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
return true;
});
// 组合两个异步任务
CompletableFuture<Void> allFutures = CompletableFuture.allOf(paymentFuture, inventoryFuture);
// 所有任务完成后执行后续操作
CompletableFuture<String> resultFuture = allFutures.thenApply(v -> {
if (paymentFuture.join() && inventoryFuture.join()) {
return "订单处理成功";
} else {
return "订单处理失败";
}
});
System.out.println(resultFuture.get());
}
}
面试考点:CompletableFuture的常用方法、异步编程模式
2. 线程池的合理配置
案例:配置适合IO密集型任务的线程池
java
import java.util.concurrent.*;
public class ThreadPoolConfigDemo {
public static void main(String[] args) {
// 计算CPU核心数
int cpuCores = Runtime.getRuntime().availableProcessors();
// 对于IO密集型任务,线程数可设置为CPU核心数的2倍
ThreadPoolExecutor executor = new ThreadPoolExecutor(
cpuCores * 2, // 核心线程数
cpuCores * 4, // 最大线程数
60L, // 空闲线程存活时间
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(100), // 任务队列
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略
);
// 提交任务
for (int i = 0; i < 20; i++) {
executor.submit(() -> {
try {
// 模拟IO操作
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " 执行任务");
});
}
executor.shutdown();
}
}
面试考点:线程池参数配置、拒绝策略选择、任务队列类型
四、JVM性能调优实战
1. 内存溢出排查
案例:模拟堆内存溢出并分析
java
import java.util.ArrayList;
import java.util.List;
public class HeapOOMDemo {
public static void main(String[] args) {
List<byte[]> list = new ArrayList<>();
// 不断创建大对象,导致堆内存溢出
while (true) {
list.add(new byte[1024 * 1024]); // 每次创建1MB的数组
}
}
}
JVM参数配置:
ruby
java -Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError HeapOOMDemo
排查步骤:
- 使用工具(如VisualVM、MAT)分析堆转储文件
- 定位内存占用最大的对象
- 检查代码中是否存在内存泄漏或过度创建大对象的情况
2. 垃圾回收器选择
案例:针对不同场景选择合适的垃圾回收器
ruby
# 新生代使用ParNew,老年代使用CMS
java -XX:+UseParNewGC -XX:+UseConcMarkSweepGC MainClass
# 使用G1垃圾回收器
java -XX:+UseG1GC -Xms4g -Xmx4g MainClass
# 使用ZGC垃圾回收器(JDK11+)
java -XX:+UseZGC -Xms8g -Xmx8g MainClass
面试考点:各垃圾回收器的特点、适用场景、调优参数
五、Spring与微服务实战
1. Spring Boot自动配置原理
案例:自定义starter开发
java
// 自动配置类
@Configuration
@ConditionalOnClass(RedisTemplate.class)
@EnableConfigurationProperties(RedisProperties.class)
public class RedisAutoConfiguration {
@Autowired
private RedisProperties properties;
@Bean
@ConditionalOnMissingBean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
// 配置序列化方式等
return template;
}
}
// 配置属性类
@ConfigurationProperties(prefix = "my.redis")
public class RedisProperties {
private String host = "localhost";
private int port = 6379;
// Getter/Setter省略
}
// META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.autoconfigure.RedisAutoConfiguration
面试考点:@Conditional注解、@ConfigurationProperties、spring.factories文件
2. Spring Cloud微服务架构
案例:基于Spring Cloud的电商微服务系统
java
// 服务注册与发现(Eureka Server)
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
// 服务提供者
@SpringBootApplication
@EnableEurekaClient
public class ProductServiceApplication {
public static void main(String[] args) {
SpringApplication.run(ProductServiceApplication.class, args);
}
}
// 服务消费者(使用OpenFeign)
@SpringBootApplication
@EnableFeignClients
public class OrderServiceApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApplication.class, args);
}
}
// Feign客户端接口
@FeignClient(name = "product-service")
public interface ProductServiceClient {
@GetMapping("/products/{id}")
Product getProduct(@PathVariable("id") Long id);
}
面试考点:服务注册与发现、服务调用、断路器、配置中心
六、数据库与ORM框架
1. MyBatis高级应用
案例:使用MyBatis实现复杂查询
xml
<!-- Mapper XML文件 -->
<select id="getUserOrders" resultMap="UserOrderResultMap">
SELECT u.*, o.*
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
WHERE u.id = #{userId}
</select>
<resultMap id="UserOrderResultMap" type="com.example.entity.User">
<id property="id" column="u_id"/>
<result property="username" column="u_username"/>
<collection property="orders" ofType="com.example.entity.Order">
<id property="id" column="o_id"/>
<result property="orderNo" column="o_order_no"/>
<result property="amount" column="o_amount"/>
</collection>
</resultMap>
面试考点:MyBatis的映射配置、动态SQL、延迟加载
2. 数据库索引优化
案例:优化电商订单查询性能
sql
-- 原查询(慢)
SELECT * FROM orders
WHERE user_id = 123
AND order_status = 'PAID'
AND create_time > '2023-01-01'
ORDER BY create_time DESC
LIMIT 10;
-- 优化方案:创建复合索引
CREATE INDEX idx_user_status_time ON orders (user_id, order_status, create_time DESC);
索引优化原则:
- 最左前缀匹配原则
- 索引列尽量避免计算和函数操作
- 区分度低的列不宜作为索引(如性别字段)
七、分布式系统实战
1. 分布式事务解决方案
案例:基于Seata的分布式事务管理
java
// 业务服务实现
@Service
public class OrderServiceImpl implements OrderService {
@Autowired
private OrderMapper orderMapper;
@Autowired
private StorageService storageService;
@Autowired
private AccountService accountService;
@GlobalTransactional // 开启全局事务
@Override
public void createOrder(Order order) {
// 1. 创建订单
orderMapper.insert(order);
// 2. 扣减库存
storageService.reduceStock(order.getProductId(), order.getCount());
// 3. 扣减账户余额
accountService.reduceBalance(order.getUserId(), order.getAmount());
}
}
面试考点:Seata的AT模式、TCC模式、Saga模式
2. 分布式缓存应用
案例:使用Redis实现商品缓存
java
@Service
public class ProductServiceImpl implements ProductService {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Autowired
private ProductMapper productMapper;
@Override
public Product getProductById(Long id) {
String key = "product:" + id;
// 先从缓存获取
Product product = (Product) redisTemplate.opsForValue().get(key);
if (product != null) {
return product;
}
// 缓存未命中,从数据库获取
product = productMapper.selectById(id);
if (product != null) {
// 放入缓存,设置过期时间
redisTemplate.opsForValue().set(key, product, 30, TimeUnit.MINUTES);
}
return product;
}
}
面试考点:缓存穿透、缓存击穿、缓存雪崩的解决方案
八、性能优化实战
1. 接口性能优化
案例:优化用户信息查询接口
java
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
// 优化前:串行调用多个服务
@GetMapping("/{id}/profile")
public ResponseEntity<UserProfile> getUserProfile(@PathVariable Long id) {
User user = userService.getUserById(id);
List<Order> orders = orderService.getOrdersByUserId(id);
Address address = addressService.getAddressByUserId(id);
UserProfile profile = new UserProfile(user, orders, address);
return ResponseEntity.ok(profile);
}
// 优化后:并行调用多个服务
@GetMapping("/{id}/profile/optimized")
public ResponseEntity<UserProfile> getUserProfileOptimized(@PathVariable Long id) {
CompletableFuture<User> userFuture = CompletableFuture.supplyAsync(() ->
userService.getUserById(id)
);
CompletableFuture<List<Order>> ordersFuture = CompletableFuture.supplyAsync(() ->
orderService.getOrdersByUserId(id)
);
CompletableFuture<Address> addressFuture = CompletableFuture.supplyAsync(() ->
addressService.getAddressByUserId(id)
);
CompletableFuture.allOf(userFuture, ordersFuture, addressFuture).join();
UserProfile profile = new UserProfile(
userFuture.join(),
ordersFuture.join(),
addressFuture.join()
);
return ResponseEntity.ok(profile);
}
}
性能对比:
- 优化前:接口响应时间约为各服务调用时间之和
- 优化后:接口响应时间约为最长服务调用时间
2. 高并发场景限流
案例:使用Sentinel实现接口限流
java
@RestController
@RequestMapping("/api/orders")
public class OrderController {
private static final String RESOURCE_KEY = "createOrder";
@PostMapping
public ResponseEntity<String> createOrder(@RequestBody OrderDTO orderDTO) {
Entry entry = null;
try {
// 资源限流
entry = SphU.entry(RESOURCE_KEY, EntryType.OUT, 1);
// 业务逻辑
orderService.createOrder(orderDTO);
return ResponseEntity.ok("订单创建成功");
} catch (BlockException e) {
// 限流处理
return ResponseEntity.status(429).body("请求过于频繁,请稍后再试");
} finally {
if (entry != null) {
entry.exit();
}
}
}
}
Sentinel配置:
java
// 初始化限流规则
private void initFlowRules() {
List<FlowRule> rules = new ArrayList<>();
FlowRule rule = new FlowRule();
rule.setResource(RESOURCE_KEY);
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
// 设置QPS阈值为100
rule.setCount(100);
rules.add(rule);
FlowRuleManager.loadRules(rules);
}
九、单元测试与代码质量
1. JUnit 5与Mockito
案例:测试订单服务
java
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
public class OrderServiceTest {
@Mock
private OrderRepository orderRepository;
@Mock
private PaymentService paymentService;
@InjectMocks
private OrderServiceImpl orderService;
@Test
public void testCreateOrderSuccess() {
// 准备测试数据
Order order = new Order();
order.setId(1L);
order.setAmount(100.0);
// 设置mock行为
when(paymentService.processPayment(any())).thenReturn(true);
when(orderRepository.save(any())).thenReturn(order);
// 执行测试
Order result = orderService.createOrder(order);
// 验证结果
assertNotNull(result);
assertEquals(1L, result.getId());
// 验证方法调用
verify(paymentService, times(1)).processPayment(order);
verify(orderRepository, times(1)).save(order);
}
}
面试考点:JUnit 5的注解、Mockito的mock与verify
2. 代码覆盖率工具
JaCoCo配置:
xml
<!-- pom.xml -->
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.8</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
执行测试并生成报告:
bash
mvn clean test
报告生成路径:target/site/jacoco/index.html
十、项目实战案例
1. 电商秒杀系统设计
架构设计:
- 流量削峰:使用Redis预加载库存,令牌桶限流
- 异步处理:订单处理放入MQ队列,异步扣减库存
- 防超卖:Redis原子操作扣减库存,数据库乐观锁防超卖
- 熔断降级:使用Sentinel熔断降级非核心服务
关键代码实现:
java
// 库存扣减(Redis实现)
public boolean deductStock(Long productId, int quantity) {
String stockKey = "seckill:stock:" + productId;
// 使用Lua脚本保证原子性
String script = "if redis.call('get', KEYS[1]) >= ARGV[1] then " +
" redis.call('decrby', KEYS[1], ARGV[1]) " +
" return 1 " +
"else " +
" return 0 " +
"end";
Long result = redisTemplate.execute(new DefaultRedisScript<>(script, Long.class),
Collections.singletonList(stockKey), quantity);
return result != null && result == 1;
}
2. 社交系统消息推送设计
技术选型:
- WebSocket实现实时推送
- Redis发布订阅实现消息广播
- 离线消息存储在MongoDB
- Kafka处理海量消息
核心代码:
java
// WebSocket处理器
@Component
public class WebSocketHandler extends TextWebSocketHandler {
private static final Map<String, WebSocketSession> sessions = new ConcurrentHashMap<>();
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
String userId = (String) session.getAttributes().get("userId");
if (userId != null) {
sessions.put(userId, session);
}
}
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
// 处理消息
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
String userId = (String) session.getAttributes().get("userId");
if (userId != null) {
sessions.remove(userId);
}
}
// 推送消息
public void pushMessage(String userId, String content) {
WebSocketSession session = sessions.get(userId);
if (session != null && session.isOpen()) {
session.sendMessage(new TextMessage(content));
}
}
}
总结
通过以上实战案例可以看出,校招Java面试不仅关注基础知识,更注重实际应用能力。建议同学们:
- 深入理解核心知识点的原理和应用场景
- 多动手实践,通过项目积累经验
- 学习使用开发工具和性能调优工具
- 关注技术发展趋势,了解最新技术动态
希望本文能帮助大家更好地准备Java校招面试,祝大家面试顺利!
以上内容补充了Java新特性、微服务、分布式系统等最新技术的实战案例,包含完整的代码实现和面试考点分析。每个章节都提供了可运行的示例代码和详细的解释,帮助你更好地理解和应用这些技术。
Java 基础,面向对象编程,集合框架,多线程,并发编程,IO 流,网络编程,Spring 框架,MyBatis, 数据库,MySQL,Spring Boot, 算法与数据结构,JVM, 校招面试
资源地址: pan.quark.cn/s/14fcf913b...