Java编程规范总结
命名:
1. 为包、类、方法、变量取一个好名字,使代码易于理解
2. 禁止使用魔鬼数字
3. 常量命名,由全大写单词组成,单词间用下划线分隔,且使用 static final修饰
4. 变量、属性命名,使用名词,并采用首字母小写的驼峰命名法
5. 方法的命名,用动词和动宾结构,并采用首字母小写的驼峰命名法
6. 类和接口的命名,采用首字母大写的驼峰命名法
7. 包的命名,由一个或若干个单词组成,所有的字母均为小写
8. 数组声明的时候使用 int[] index,而不要使用 int index[]
注释:
1. 尽量用代码来解释自己
2. 注释应解释代码的意图,而不是描述代码怎么做的
3. 保证注释与代码一致,避免产生误导
4. 注释应与其描述代码位置相邻,放在所注释代码上方或右方,并与代码采用同样缩进
5. 不要用注释保留废弃代码
6. 不要用注释记录修改日志
7. 一般单行注释用//,块注释用,JavaDoc注释用
排版:
1. 团队应遵守一致的排版风格
2. 将排版风格固化到IDE的代码格式化配置文件中,并让整个团队使用
3. 在不同的概念之间,增加空行
4. 将逻辑紧密相关的代码放在一起
5. 控制一行的宽度,不要超过120个字符
6. 在不同的概念间(关键字、变量、操作符等)增加空格,以便清楚区分概念
7. 采用缩进来区分不同层次的概念
8. 将局部变量的作用域最小化
9. 给if、for、do、while、switch等语句的执行体加大括号{}
10. 控制文件的长度,最好不要超过500行
变量和类型:
1. 谨慎使用静态成员变量
2. 避免随意进行类型强制转换,应改善设计,或在转换前用instanceof进行判断3
3. 需要精确计算时不要使用float和double
4. 不能用浮点数作为循环变量
5. 浮点型数据判断相等不能直接使用==
6. 避免同一个局部变量在前后表达不同的含义
7. 不要在单个的表达式中对相同的变量赋值超过一次
8. 基本类型优于包装类型,注意合理使用包装类型
方法:
1. 方法设计的第一原则是要短小
2. 方法设计应遵循单一职责原则(SRP),一个方法仅完成一个功能
3. 方法设计应遵循单一抽象层次原则(SLAP)
4. 方法设计应遵循命令与查询职责分离原则(CQRS)
5. 不要把方法的入参当做工作变量/临时变量,除非特别需要
6. 使用类名调用静态方法,而不要使用实例或表达式来调用
7. 应明确规定对接口方法参数的合法性检查由调用者负责还是由接口方法本身负责
8. 方法的参数个数不宜过多
9. 谨慎使用可变数量参数的方法
包、类和接口:
1. 类和接口的设计应遵循面向对象SOLID设计原则
2. 类的设计应遵循迪米特法则
3. 类的设计应遵循“Tell,Don't ask”原则
4. 类设计时优选组合而不是继承
5. 除提供给外部使用的全局常量外,应尽量避免类成员变量被外部直接访问
6. 避免在无关的变量或无关的概念之间重用名字,避免隐藏(hide)、遮蔽(shadow)和遮掩(obscure)
7. 覆写(override)——子类与父类间
8. 重载(overload)——类内部
9. 隐藏(hide)——子类与父类间
10. 遮蔽(shadow)——类内部
11. 遮掩(obscure)——类内部
12. 不要在父类的构造方法中调用可能被子类覆写的方法
13. 覆写equals方法时,应同时覆写hashCode方法
14. 子类覆写父类方法时应加上@Override注解
15. 接口定义中去掉多余的修饰词
16. 设计时,考虑类的可变性最小化
异常:
1. 只针对真正异常的情况才使用exception机制
2. 在抛出异常的细节信息中,应包含能捕获失败的信息
3. 对可恢复的情况使用受检异常(checked exception),对编程错误使用运行时异常(runtime exception)
4. 不要忽略异常
5. 方法注释和文档中要包含所抛出异常的说明
6. 方法抛出的异常,应该与本身的抽象层次相对应
7. 对第三方API抛出大量各类异常进行封装
8. 使用异常来做错误处理,而非错误码
9. 在finally块中不要使用return、break或continue使finally块非正常结束
10. 不要直接捕获受检异常的基类Exception
11. 一个方法不应抛出太多类型的异常
12. 充分利用断言
日志:
1. 日志信息准确、繁简得当,满足快速定位的需要
2. 日志的记录,不要使用 System.out 与 System.err 进行控制台打印,应该使用专用的日志工具(比如:slf4j+logback)进行处理
3. 日志工具对象logger应声明为private static final
4. 日志应分等级
5. 日志中不要记录敏感信息
多线程并发:
1. 多线程访问同一个可变变量,需增加同步机制
2. 禁止不加控制地创建新线程
3. 创建新线程时需指定线程名
4. 使用Thread对象的setUncaughtExceptionHandler方法注册Runtime异常的处理者(v1.5+)
5. 不要使用Thread.stop方法,因为该方法本质是不安全的,使用它可能会导致数据遭到破坏
6. 不要依赖线程调度器、线程优先级和yield()方法
7. 采用Java1.5提供新并发工具代替wait和notify(v1.5+)
8. 使用线程安全集合在多线程间共享可变数据
9. 多线程操作同一个字符串相加,应采用StringBuffer
10. 针对线程安全性,需要进行文档(javadoc)说明
运算和表达式:
1. 不要写复杂的表达式
2. 运算时应避免产生溢出
3. 采用括号明确运算的优先级
控制语句:
1. 采用for-each代替传统的for循环(v1.5+)
2. 在switch语句的每一个case、和default中都放置一条break语句
序列化:
1. 尽量不要实现Serializable接口
2. 序列化对象中的HashMap、HashSet或HashTable等集合不能包含对象自身的引用
3. 实现Serializable接口的可序列化类应该显式声明 serialVersionUID
泛型:
1. 在集合中使用泛型(v1.5+)
2. 类的设计可优先考虑泛型(v1.5+)
3. 方法的设计可优先考虑泛型(v1.5+)
4. 优先使用泛型集合,而不是数组(v1.5+)
其他语言特性:
1. 新代码不要使用已标注为@deprecated的方法
2. 使用JDK自带的API或广泛使用的开源库,不要自己写类似的功能。
3. 升级到最新稳定版的Java 平台版本上,以便获取新特性带来的收益
4. 充分利用编译器的告警选项
5. 使用字符串API时,应注意方法使用的是否是 “正则表达式”
6. 值类(value classes)的设计,可考虑实现Comparable接口,方便在集合中实现对象的搜索、排序、计算极值等
性能:
1. 谨慎地进行性能优化
2. 使用System.arraycopy()进行数组复制
3. 使用集合的toArray()方法将集合转为数组(v1.42+)
4. 在Java的IO操作中,尽量使用带缓冲的实现
资源管理:
1. 避免创建不必要的对象
2. 将对象存入HashSet,或作为key存入HashMap(或HashTable)后,必须确保该对象的hashcode值不变,避免因为hashcode值变化导致不能从集合内删除该对象,进而引起内存泄漏的问题
3. 执行IO操作时,应该在finally里关闭IO资源
4. 消除过期的对象引用
可移植性:
1. 不要在代码中硬编码"\n"和"\r"作为换行符号
2. 谨慎地使用本地方法
3. 避免对第三方代码的强依赖或陷入第三方代码细节
国际化:
1. 在所有的输入输出环节,指明正确的编码方式,进行正确的字符到字节,或字节到字符的转换
2. 如果输入源或输出目标直接支持,尽可能直接使用Unicode进行输入输出。
3. 不要依赖平台默认的字符编码方式。
4. 对于使用默认编码方式的第三方代码或者遗留代码,可应用适配器模式,将返回的字符串转换成Unicode内码
5. 字符串大小写转换时,应加上Locale.US
参考资料及扩展阅读材料:
1.《Java语言编程规范》
2.《核心网Java编程军规 v1.0》
3.《Java Coding Conventions》
4.《Effective Java 第二版》
5.《代码整洁之道》
6.《Java解惑》
7.《Java编程思想》
安全性:
1 数据校验:
规则 1.1 校验跨信任边界传递的不可信数据
规则 1.2 禁止直接使用不可信数据来拼接SQL语句
规则 1.3 禁止直接使用不可信数据来拼接XML
规则 1.4 禁止直接使用不可信数据来记录日志
规则 1.5 从格式化字符串中排除用户输入
规则 1.6 禁止向Runtime.exec() 方法传递不可信、未净化的数据
规则 1.7 验证路径之前应该先将其标准化
规则 1.8 安全地从ZipInputStream提取文件
2 异常行为:
规则 2.1 不要抑制或者忽略已检查异常
规则 2.2 禁止在异常中泄露敏感信息
规则 2.3 方法发生异常时要恢复到之前的对象状态
3 I/O操作:
规则 3.1 临时文件使用完毕应及时删除
规则 3.2 不要将Buffer对象封装的数据暴露给不可信代码
规则 3.3 在多用户系统中创建文件时指定合适的访问许可
规则 3.4 避免让外部进程阻塞在输入输出流上
规则 3.5 避免在共享目录操作文件
4 序列化和反序列化:
规则 4.1 将敏感对象发送出信任区域前进行签名并加密
规则 4.2 禁止序列化未加密的敏感数据
规则 4.3 防止序列化和反序列化被利用来绕过安全管理
5 平台安全:
规则 5.1 使用安全管理器来保护敏感操作
规则 5.2 防止特权区域内出现非法的数据
规则 5.3 禁止基于不信任的数据源做安全检查
规则 5.4 禁止特权块向非信任域泄漏敏感信息
规则 5.5 编写自定义类加载器时应调用超类的getPermission()函数
规则 5.6 避免完全依赖URLClassLoader和java.util.jar提供的默认自动签名认证机制
6 运行环境:
规则 6.1 禁止给仅执行非特权操作的代码签名
规范 6.2 不要使用危险的许可与目标组合
规则 6.3 不要禁用字节码验证
规则 6.4 禁止部署的应用可被远程监控
规则 6.5 将所有安全敏感代码都放在一个jar包中,签名再加密
规则 6.6 不要信任环境变量的值
规则 6.6 生产代码不能包含任何调试入口点
7 其他:
规则 7.1 禁止在日志中保存口令、密钥和其他敏感数据
规则 7.2 禁止使用私有或者弱加密算法
规则 7.3 基于哈希算法的口令安全存储必须加入盐值(salt)
规则 7.4 禁止将敏感信息硬编码在程序中
规则 7.5 使用强随机数
规则 7.6 防止将系统内部使用的锁对象暴露给不可信代码
规则 7.7 使用SSLSocket代替Socket来进行安全数据交互
规则 7.8 封装本地方法调用