当前位置: 首页 > news >正文

[代码规范篇]Java代码规范

[代码规范篇]Java代码规范

本文旨在介绍Java代码在编写、设计时的一些注意点,帮助后端新人养成一个好习惯,同时规范开发,需要注意的是本文内容不全,以及不同公司一些规范可能有差别,大家以自己司内风格为准即可。

想要看Go规范的同学,可以参考这篇文档: [代码规范篇]Go代码规范

  • 不同公司之间,编码规范都有不同,大家自行灵活变通即可,但大体方向相差无几。
  • 大家也可以去看阿里巴巴出的Java编码规范,里面有更细致的讲解:《阿里巴巴Java开发手册(终极版)》免费在线阅读_藏经阁

在这里插入图片描述

1. 资源管理

原则:

  • 及时释放资源:使用 try-with-resources 或 finally 块确保资源被正确关闭
  • 避免资源泄漏:数据库连接、文件句柄、网络连接等必须显式关闭
  • 空值检查:访问对象前必须进行空值检查
// 不推荐:未关闭资源
public String readFile(String filename) throws IOException {FileInputStream fis = new FileInputStream(filename);byte[] data = fis.readAllBytes();return new String(data);
}// 推荐:使用 try-with-resources 自动关闭资源
public String readFile(String filename) throws IOException {try (FileInputStream fis = new FileInputStream(filename)) {byte[] data = fis.readAllBytes();return new String(data);}
}// 不推荐:未检查空值
public void processUser(User user) {System.out.println(user.getName()); // 可能抛出 NullPointerException
}// 推荐:检查空值
public void processUser(User user) {if (user == null) {return;}System.out.println(user.getName());
}

2. 并发安全

原则:

  • 明确数据所有权:清晰界定哪些线程可以访问和修改哪些数据
  • 锁范围最小化:减少锁的持有时间,只锁住临界区
  • 优先使用并发工具类:使用 java.util.concurrent 包中的工具类
  • 避免死锁:统一加锁顺序,避免循环等待
// 不推荐:在锁中执行耗时操作
public void badExample(Lock lock, Map<String, Integer> data) throws InterruptedException {lock.lock();try {// 模拟耗时操作Thread.sleep(1000);data.put("key", 1);} finally {lock.unlock();}
}// 推荐:尽快释放锁
public void goodExample(Lock lock, Map<String, Integer> data) throws InterruptedException {lock.lock();try {data.put("key", 1);} finally {lock.unlock();}// 耗时操作在锁外执行Thread.sleep(1000);
}

3. 敏感信息安全

原则:

  • 最小权限原则:只赋予程序运行所需的最小权限
  • 输入校验:对所有外部输入进行严格的长度、类型、格式校验
  • 敏感信息保护:避免硬编码密钥、密码等敏感信息
  • 防止SQL注入:使用预编译语句
// 不推荐:硬编码敏感信息
private static final String DB_PASSWORD = "root123";// 推荐:通过环境变量或配置文件读取
public String getDBPassword() {return System.getenv("DB_PASSWORD");
}// 不推荐:容易造成SQL注入
public User getUserById(String id) throws SQLException {String sql = "SELECT * FROM users WHERE id = " + id;Statement stmt = connection.createStatement();ResultSet rs = stmt.executeQuery(sql);// ...return null;
}// 推荐:使用PreparedStatement防止SQL注入
public User getUserById(String id) throws SQLException {String sql = "SELECT * FROM users WHERE id = ?";try (PreparedStatement pstmt = connection.prepareStatement(sql)) {pstmt.setString(1, id);try (ResultSet rs = pstmt.executeQuery()) {// 处理结果集return null;}}
}

4. 日志

原则:

  • 恰当使用日志级别:根据信息重要性选择合适的日志级别
  • 避免敏感信息:日志中不记录密码、密钥等敏感信息
  • 包含上下文信息:日志应包含足够的上下文信息便于排查问题
  • 使用参数化日志:避免字符串拼接提高性能
// 不推荐:日志级别使用不当
logger.info("User login failed"); // 应该使用warn级别。具体级别根据实际业务场景来综合评判// 推荐:恰当使用日志级别
logger.debug("Processing user data for user ID: {}", userId);
logger.info("User {} logged in successfully", userId);
logger.warn("Login failed for user: {}", userId);
logger.error("Database connection failed", exception);// 不推荐:记录敏感信息
logger.info("User password: {}", password);// 推荐:避免记录敏感信息
logger.info("User login attempt for user: {}", username);

5. 异常处理

原则:

  • 正确处理异常:不能忽略异常,应处理或传递
  • 保留异常链:保留原始异常信息便于问题排查
  • 具体异常类型:抛出具体的异常类型而非通用异常
  • 避免空catch块:不能捕获异常却不处理
// 不推荐:忽略异常
public String readFile(String filename) {try {return new String(Files.readAllBytes(Paths.get(filename)));} catch (IOException e) {return ""; // 忽略异常}
}// 推荐:处理异常
public String readFile(String filename) throws IOException {try {return new String(Files.readAllBytes(Paths.get(filename)));} catch (IOException e) {logger.error("Failed to read file: {}", filename, e);throw new IOException("Failed to read file: " + filename, e);}
}

6. 测试

原则:

  • 单元测试覆盖:关键逻辑和公开方法必须有单元测试
  • 测试独立性:每个测试方法应独立,不依赖其他测试
  • 依赖注入:通过接口而非具体实现便于Mock测试
  • 边界条件测试:测试正常、异常和边界条件
// 定义接口以便mock
public interface UserRepository {User findById(Long id);void save(User user);
}// 使用Mock进行测试
@Test
public void testFindUserById() {// GivenUserRepository mockRepository = mock(UserRepository.class);UserService userService = new UserService(mockRepository);User expectedUser = new User(1L, "John");when(mockRepository.findById(1L)).thenReturn(expectedUser);// WhenUser actualUser = userService.findUserById(1L);// ThenassertEquals(expectedUser, actualUser);verify(mockRepository).findById(1L);
}

7. 性能

原则:

  • 避免重复计算:缓存计算结果,避免重复计算
  • 合理使用集合:选择合适的数据结构和初始容量
  • 字符串处理优化:大量字符串拼接使用 StringBuilder
  • 避免内存泄漏:及时清理不用的对象引用
// 不推荐:重复计算
public double calculateTotalWithTax(List<Order> orders) {double total = 0;for (Order order : orders) {// 每次循环都调用getTaxRate(),如果这是个昂贵的操作就浪费了total += order.getAmount() * (1 + getTaxRate());}return total;
}// 推荐:避免重复计算
public double calculateTotalWithTax(List<Order> orders) {// 只计算一次税率double taxRate = getTaxRate();double total = 0;for (Order order : orders) {total += order.getAmount() * (1 + taxRate);}return total;
}

8. 项目设计

原则:

  • 分层架构:采用清晰的分层架构(Controller-Service-Repository)
  • 单一职责:每个类只负责一个功能领域
  • 依赖倒置:依赖抽象而非具体实现
  • 开闭原则:对扩展开放,对修改关闭
// Controller层
@RestController
@RequestMapping("/users")
public class UserController {private final UserService userService;public UserController(UserService userService) {this.userService = userService;}@PostMappingpublic ResponseEntity<UserDTO> createUser(@RequestBody CreateUserRequest request) {User user = userService.createUser(request.getName(), request.getEmail());return ResponseEntity.ok(UserDTO.from(user));}
}

9. 接口设计

原则:

  • 接口隔离:使用专门的接口,而不是庞大的总接口
  • 默认方法:合理使用默认方法提供通用实现
  • 明确契约:接口方法应有明确的契约和文档说明
// 不推荐:臃肿的接口
public interface BadUserService {User createUser(String name, String email);User updateUser(Long id, String name, String email);void deleteUser(Long id);List<User> getAllUsers();User findUserById(Long id);List<User> findUsersByName(String name);void sendEmail(Long userId, String content);void sendSms(Long userId, String content);void generateReport();void backupData();// 更多不相关的方法...
}// 推荐:接口隔离
public interface UserManagementService {User createUser(String name, String email);User updateUser(Long id, String name, String email);void deleteUser(Long id);List<User> getAllUsers();User findUserById(Long id);List<User> findUsersByName(String name);
}public interface NotificationService {void sendEmail(Long userId, String content);void sendSms(Long userId, String content);
}public interface ReportingService {void generateReport();
}public interface BackupService {void backupData();
}// 不推荐:接口方法缺乏文档说明
public interface UserService {User findUser(Long id);List<User> searchUsers(String keyword);
}// 推荐:明确的接口契约
/*** 用户服务接口,提供用户管理相关功能*/
public interface UserService {/*** 根据ID查找用户* @param id 用户ID,不能为空且必须大于0* @return 用户对象,如果未找到返回null* @throws IllegalArgumentException 当ID无效时抛出*/User findUser(Long id);/*** 根据关键字搜索用户* @param keyword 搜索关键字,不能为空* @return 匹配的用户列表,不会返回null* @throws IllegalArgumentException 当关键字为空时抛出*/List<User> searchUsers(String keyword);
}

10. 类设计

原则:

  • 封装性:合理使用访问修饰符,隐藏内部实现
  • 不可变性:对于值对象,尽量设计为不可变类
  • 继承与组合:优先使用组合而非继承
  • 构造函数设计:提供清晰的构造函数和工厂方法
// 不推荐:封装性差,缺乏不可变性
public class BadUser {public Long id;           // 应该是privatepublic String name;       // 应该是privatepublic String email;      // 应该是privatepublic BadUser(Long id, String name, String email) {this.id = id;this.name = name;this.email = email;}
}// 不推荐:使用继承而非组合
public class BadUserService extends DatabaseConnection {public User findUser(Long id) {return queryUser(id); // 直接使用父类方法}
}// 推荐:良好的封装性
public class GoodUser {private final Long id;private final String name;private final String email;public GoodUser(Long id, String name, String email) {this.id = Objects.requireNonNull(id, "ID cannot be null");this.name = Objects.requireNonNull(name, "Name cannot be null");this.email = Objects.requireNonNull(email, "Email cannot be null");}// 只提供getter,不提供setter保证不可变性public Long getId() { return id; }public String getName() { return name; }public String getEmail() { return email; }
}// 推荐:使用组合而非继承
public class GoodUserService {private final DatabaseConnection databaseConnection; // 组合public GoodUserService(DatabaseConnection databaseConnection) {this.databaseConnection = Objects.requireNonNull(databaseConnection);}public User findUser(Long id) {return databaseConnection.queryUser(id);}
}// 推荐:清晰的构造函数设计
public class Order {private final Long id;private final String orderNumber;private final BigDecimal amount;private OrderStatus status;// 主要构造函数public Order(Long id, String orderNumber, BigDecimal amount) {this.id = Objects.requireNonNull(id);this.orderNumber = Objects.requireNonNull(orderNumber);this.amount = Objects.requireNonNull(amount);this.status = OrderStatus.CREATED;}// 静态工厂方法提供语义化创建public static Order newOrder(String orderNumber, BigDecimal amount) {return new Order(IdGenerator.next(), orderNumber, amount);}// 业务方法而非setterpublic void confirm() {this.status = OrderStatus.CONFIRMED;}// getterspublic Long getId() { return id; }public String getOrderNumber() { return orderNumber; }public BigDecimal getAmount() { return amount; }public OrderStatus getStatus() { return status; }
}

11. 命名规范

原则:

  • 文件名与类名一致:Java源文件名必须与公共类名完全一致;
  • 包名规范:使用小写字母,用点分隔,体现项目结构;
  • 目录结构清晰:按照包结构组织源文件目录
  • 类名使用大驼峰:首字母大写,每个单词首字母大写
  • 方法名使用小驼峰:首字母小写,每个单词首字母大写
  • 变量名表意明确:避免使用单字母或无意义的缩写
  • 常量全大写:使用下划线分隔单词
// 不推荐:命名不规范
public class user_service {private string user_name;private int userage;public void GET_USER() {// ...}
}// 推荐:规范命名
public class UserService {private String userName;private int userAge;private static final int MAX_RETRY_COUNT = 3;public void getUser() {// ...}
}// 不推荐:变量名无意义
public void processData() {int d;        // 什么的天数?String s;     // 什么字符串?List a;       // 什么列表?
}// 推荐:表意明确的命名
public void processData() {int timeoutDays;String errorMessage;List<User> activeUsers;
}// 不推荐:常量命名不规范
private static final int maxcount = 100;
private static final String default_url = "http://localhost";// 推荐:常量规范命名
private static final int MAX_COUNT = 100;
private static final String DEFAULT_URL = "http://localhost";

12. 代码格式

原则:

  • 统一缩进:使用4个空格进行缩进,不使用tab
  • 合理空行:方法之间、逻辑块之间使用空行分隔
  • 规范注释:公共类、方法必须有JavaDoc注释
  • 空格规范:操作符、关键字周围使用适当空格
// 不推荐:缩进不一致
public class BadFormatting {
public void method(){
if(condition){
doSomething();
}
}
}// 推荐:统一4空格缩进
public class GoodFormatting {public void method() {if (condition) {doSomething();}}
}// 不推荐:缺少空行分隔
public class BadSpacing {private String name;private int age;public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}
}// 推荐:合理使用空行
public class GoodSpacing {private String name;private int age;public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}
}// 不推荐:缺少注释
public class BadDocumentation {public User findUser(Long id) {// 实现return null;}
}// 推荐:完善的注释
/*** 用户服务类,提供用户相关的业务操作* * @author Developer* @since 1.0.0*/
public class GoodDocumentation {/*** 根据用户ID查找用户信息* * @param id 用户ID,必须大于0* @return 用户对象,如果未找到返回null* @throws IllegalArgumentException 当ID小于等于0时抛出*/public User findUser(Long id) {if (id == null || id <= 0) {throw new IllegalArgumentException("Invalid user ID: " + id);}// 实现return null;}
}// 不推荐:空格使用不规范
public void badSpacing(){
int a=1+2;
boolean result=(a>1)?true:false;
}// 推荐:规范的空格使用
public void goodSpacing() {int a = 1 + 2;boolean result = (a > 1) ? true : false;
}

参考文章:https://developer.aliyun.com/ebook/386/read?spm=a2c6h.26392459.ebook-detail.2.63392867ZUEhqw


文章转载自:

http://YpDEXMLE.ssgLh.cn
http://JUgnSjAY.ssgLh.cn
http://oWAsZyB8.ssgLh.cn
http://KXviXugy.ssgLh.cn
http://0g8e2uTU.ssgLh.cn
http://ibdLFP83.ssgLh.cn
http://zyiZXf9a.ssgLh.cn
http://LIQbDUbl.ssgLh.cn
http://dCGaCE4C.ssgLh.cn
http://l8iP5ncf.ssgLh.cn
http://dHVIcKCH.ssgLh.cn
http://WYFsArLz.ssgLh.cn
http://UmL2xjxb.ssgLh.cn
http://Wc6cNAev.ssgLh.cn
http://C0pkkslw.ssgLh.cn
http://Tbsuos5U.ssgLh.cn
http://fXpxxrBn.ssgLh.cn
http://UbipPK9U.ssgLh.cn
http://TyETxXTl.ssgLh.cn
http://Vc7jXosV.ssgLh.cn
http://ZMPZzvp6.ssgLh.cn
http://NQyUWLRo.ssgLh.cn
http://OWEnGrXk.ssgLh.cn
http://1UO7DfKN.ssgLh.cn
http://ip52b0cf.ssgLh.cn
http://nCjKmaft.ssgLh.cn
http://kL1umMbB.ssgLh.cn
http://VwdwoQnI.ssgLh.cn
http://c9uh8e4a.ssgLh.cn
http://VnJlw84T.ssgLh.cn
http://www.dtcms.com/a/385263.html

相关文章:

  • C++:string模拟实现中的赋值拷贝函数现代写法诡异地崩掉了......
  • 构建AI大模型对话系统
  • Linux基本指令(9)
  • 64_基于深度学习的蝴蝶种类检测识别系统(yolo11、yolov8、yolov5+UI界面+Python项目源码+模型+标注好的数据集)
  • 3-12〔OSCP ◈ 研记〕❘ WEB应用攻击▸利用XSS提权
  • 3dma渲染噪点成因排查及优化方案
  • Lombok
  • React Scheduler(调度器)
  • 多任务数据集的具体使用场景
  • KITTI数据集
  • 什么云服务器更好用推荐一下!?
  • 根据Linux内核原理 LRU链表如何知道page的活动频繁程度?
  • 2025全球LoRaWAN模组技术对比与应用方案解析
  • 社区主题征文——「异构融合与存算一体:架构探索与创新实践」算力技术征文
  • Jenkins参数化构建
  • SIPJS对接FreeSWITCH强制媒体流走coturn relay地址
  • docker registry 私服搭建教程
  • 清除gradle缓存的某个依赖
  • MCP引导Agent示例
  • 【HTTP 响应状态码】从零到实战
  • 航线系统对频模块技术要点
  • 二十、DevOps落地:Jenkins基础入门(一)
  • 计网1.1
  • DDD领域驱动设计
  • 传智播客--MySQL
  • 不同 HLA II 类等位基因(HLA-DRB1*15:02)与 cGVHD 的关联差异
  • 【AI 辅助工作工具集合】持续更新
  • 核心信息防爬虫盗取技术方案
  • Linux网络:序列化和反序列化
  • Java 代理模式-JDK动态代理