java的编码规范
命名规范
数组
类型与中括号紧挨相连来表⽰数组
正例:定义整形数组 int[] arrayDemo;
反例:在 main 参数中,使⽤ String args[]来定义。
POJO 类中布尔类型的变量
POJO 类中布尔类型的变量,都不要加 is 前缀,否则部分框架解析会引起序列化错误。
反例:定义为基本数据类型 Boolean isDeleted 的属性,它的⽅法也是 isDeleted(),RPC阿⾥巴巴 Java 开发⼿册
框架在反向解析的时候,“误以为”对应的属性名称是 deleted,导致属性获取不到,进⽽抛
出异常。
涉及设计模式命名
如果模块、接⼝、类、⽅法使⽤了设计模式,在命名时需体现出具体模式。
说明:将设计模式体现在名字中,有利于阅读者快速理解架构设计理念。
正例:public class OrderFactory;
public class LoginProxy;
public class ResourceObserver;
接⼝类中的⽅法和属性
接⼝类中的⽅法和属性不要加任何修饰符号(public 也不要加),保持代码的简洁性,并加上有效的 Javadoc 注释。尽量不要在接⼝⾥定义变量,如果⼀定要定义变量,肯定是 与接⼝⽅法相关,并且是整个应⽤的基础常量。
正例:接⼝⽅法签名 void commit();
接⼝基础常量 String COMPANY = “alibaba”;
反例:接⼝⽅法定义 public abstract void f();
说明:JDK8 中接⼝允许有默认实现,那么这个 default ⽅法,是对所有实现类都有价值的默
认实现。
接⼝和实现类的命名
1)对于 Service 和 DAO 类,基于 SOA 的理念,暴露出来的服务⼀定是接⼝,内部 的实现类⽤ Impl 的后缀与接⼝区别。
正例:CacheServiceImpl 实现 CacheService 接⼝。
2)如果是形容能⼒的接⼝名称,取对应的形容词为接⼝名(通常是–able 的形式)。
正例:AbstractTranslator 实现 Translatable 接⼝。
Enum
枚举类名建议带上 Enum 后缀,枚举成员名称需要全⼤写,单词间⽤下划线隔开。
说明:枚举其实就是特殊的类,域成员均为常量,且构造⽅法被默认强制是私有。
正例:枚举名字为 ProcessStatusEnum 的成员名称:SUCCESS / UNKNOWN_REASON。
常量定义
Long赋值
在 long 或者 Long 赋值时,数值后使⽤⼤写的 L,不能是⼩写的 l,⼩写容易跟数字 1 混淆,造成误解。说明:Long a = 2l; 写的是数字的 21,还是 Long 型的 2?
常量类
不要使⽤⼀个常量类维护所有常量,要按常量功能进⾏归类,分开维护。
说明:⼤⽽全的常量类,杂乱⽆章,使⽤查功能才能定位到修改的常量,不利于理解和维护。
正例:缓存相关常量放在类 CacheConsts 下;系统配置相关常量放在类 ConfigConsts 下
enum
如果变量值仅在⼀个固定范围内变化⽤ enum 类型来定义。
说明:如果存在名称之外的延伸属性应使⽤ enum 类型,下⾯正例中的数字就是延伸信息,表
⽰⼀年中的第⼏个季节。
正例:
public enum SeasonEnum {
SPRING(1),SUMMER(2),AUTUMN(3),WINTER(4);
private int seq;
SeasonEnum(int seq){
this.seq = seq;
}
}
代码风格
单⾏字符数限制不超过 120 个
超出需要换⾏,换⾏时遵循如下原则:
1) 第⼆⾏相对第⼀⾏缩进 4 个空格,从第三⾏开始,不再继续缩进,参考⽰例。
2) 运算符与下⽂⼀起换⾏。
3) ⽅法调⽤的点符号与下⽂⼀起换⾏。
4) ⽅法调⽤中的多个参数需要换⾏时,在逗号后进⾏。
5) 在括号前不要换⾏,见反例。
正例:
StringBuffer sb =new StringBuffer();
// 超过 120 个字符的情况下,换⾏缩进 4 个空格,点号和⽅法名称⼀起换⾏
sb.append("zi").append("xin")...
.append("huang")...
.
append("huang")...
.append("huang");
反例:
StringBuffer sb =new StringBuffer();
// 超过 120 个字符的情况下,不要在括号前换⾏
sb.append("zi").append("xin")...append
("huang");
// 参数很多的⽅法调⽤可能超过 120 个字符,不要在逗号前换⾏
method(args1, args2, args3,...
, argsX);
单个⽅法的总⾏数不超过 80 ⾏
说明:包括⽅法签名、结束右⼤括号、⽅法内代码、注释、空⾏、回车及任何不可见字符的总
⾏数不超过 80 ⾏。
正例:代码逻辑分清红花和绿叶,个性和共性,绿叶逻辑单独出来成为额外⽅法,使主⼲代码
更加清晰;共性逻辑抽取成为共性⽅法,便于复⽤和维护。
OOP规约
Object 的 equals ⽅法
Object 的 equals ⽅法容易抛空指针异常,应使⽤常量或确定有值的对象来调⽤ equals。
正例:“test”.equals(object);
反例:object.equals(“test”);
说明:推荐使⽤ java.util.Objects#equals(JDK7 引⼊的⼯具类)
equals ⽅法⽐较
所有的相同类型的包装类对象之间值的⽐较,全部使⽤ equals ⽅法⽐较。
说明:对于 Integer var = ? 在-128 ⾄ 127 范围内的赋值,Integer 对象是在 IntegerCache.cache 产⽣,会复⽤已有对象,这个区间内的 Integer 值可以直接使⽤==进⾏判断,但是这个区间之外的所有数据,都会在堆上产⽣,并不会复⽤已有对象,推荐使⽤ equals ⽅法进⾏判断。
POJO 类 toString ⽅法
POJO 类必须写 toString ⽅法。使⽤ IDE 中的⼯具:source> generate toString 时,如果继承了另⼀个 POJO 类,注意在前⾯加⼀下String。
说明:在⽅法执⾏抛出异常时,可以直接调⽤ POJO 的 toString()⽅法打印其属性值,便于排
查问题。
String 的 split ⽅法
使⽤索引访问⽤ String 的 split ⽅法得到的数组时,需做最后⼀个分隔符后有⽆内容的检查,否则会有抛 IndexOutOfBoundsException 的风险。
说明:
String str ="a,b,c,,";
String[] ary = str.split(",");
// 预期⼤于 3,结果是 3java switch case string
System.out.println(ary.length);
StringBuilder 的 append
循环体内,字符串的连接⽅式,使⽤ StringBuilder 的 append ⽅法进⾏扩展。
说明:下例中,反编译出的字节码⽂件显⽰每次循环都会 new 出⼀个 StringBuilder 对象,然后进⾏ append 操作,最后通过 toString ⽅法返回 String 对象,造成内存资源浪费。
反例:
String str ="start";
for(int i =0; i <100; i++){
str = str +"hello";
}
集合处理
subList
ArrayList的subList结果不可强转成ArrayList否则会抛出ClassCastException异常,即 java.util.RandomAccessSubList cannot be cast to java.util.ArrayList。
说明:subList 返回的是 ArrayList 的内部类 SubList,并不是 ArrayList ⽽是 ArrayList 的⼀个视图,对于 SubList ⼦列表的所有操作最终会反映到原列表上。
在subList中⾼度注意对原集合元素的增加或删除,均会导致⼦列表的遍历、增加、删除产⽣ ConcurrentModificationException 异常。Arrays.asList()
使⽤⼯具类 Arrays.asList()把数组转换成集合时,不能使⽤其修改集合相关的⽅法,它的 add/remove/clear ⽅法会抛出UnsupportedOperationException 异常。
说明:asList 的返回对象是⼀个 Arrays 内部类,并没有实现集合的修改⽅法。Arrays.asList 体现的是适配器模式,只是转换接⼝,后台的数据仍是数组。
String[] str =new String[]{"you","wu"};
List list = Arrays.asList(str);
第⼀种情况:list.add("yangguanbao"); 运⾏时异常。
第⼆种情况:str[0] = "gujin"; 那么 (0)也会随之修改。
泛型通配符
泛型通配符<? extends T>来接收返回的数据,此写法的泛型集合不能使⽤ add ⽅法,⽽<? super T>不能使⽤ get ⽅法,作为接⼝调⽤赋值时易出错。
说明:扩展说⼀下 PECS(Producer Extends Consumer Super)原则:
第⼀、频繁往外读取内容的,适合⽤<? extends T>。
第⼆、经常往⾥插⼊的,适合⽤<? super T>。
foreach 的 remove/add 操作
不要在 foreach 循环⾥进⾏元素的 remove/add 操作。remove 元素请使⽤ Iterator ⽅式,如果并发操作,需要对 Iterator 对象加锁。
正例:
List\<String> list =new ArrayList<>();
list.add("1");
list.add("2");
Iterator\<String> iterator = list.iterator();
while(iterator.hasNext()){
String item = ();
if(删除元素的条件){
}
}
反例:
for(String item : list){
if("1".equals(item)){
}
}
集合初始化时,指定集合初始值
说明:HashMap 使⽤ HashMap(int initialCapacity) 初始化。
正例:initialCapacity = (需要存储的元素个数 / 负载因⼦) + 1。注意负载因⼦(即 loader factor)默认为 0.75,如果暂时⽆法确定初始值⼤⼩,请设置为 16(即默认值)。
反例:HashMap 需要放置 1024 个元素,由于没有设置容量初始⼤⼩,随着元素不断增加,容量 7 次被迫扩⼤,resize 需要重建 hash 表,严重影响性能。
使⽤ entrySet 遍历 Map 类集合 KV
说明:keySet 其实是遍历了 2 次,⼀次是转为 Iterator 对象,另⼀次是从 hashMap 中取出
key 所对应的 value。⽽ entrySet 只是遍历了⼀次就把 key 和 value 都放到了 entry 中,效
率更⾼。如果是 JDK8,使⽤ Map.foreach ⽅法。
正例:values()返回的是 V 值集合,是⼀个 list 集合对象;keySet()返回的是 K 值集合,是⼀个 Set 集合对象;entrySet()返回的是 K-V 值组合集合。
Map 类集合 K/V 能不能存储 null 值的情况
集合类 Key Value Super 说明
[外链图⽚转存失败,源站可能有防盗链机制,建议将图⽚保存下来直接上传(img-ITWGpxz3-1581644492704)(…/
…
/pic/1567475464289.png)]
反例: 由于 HashMap 的⼲扰,很多⼈认为 ConcurrentHashMap 是可以置⼊ null 值,⽽事实上,
存储 null 值时会抛出 NPE 异常。
集合去重
利⽤ Set 元素唯⼀的特性,可以快速对⼀个集合进⾏去重操作,避免使⽤ List 的
contains ⽅法进⾏遍历、对⽐、去重操作。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论