编码5分钟,优化两小时? 如何更规范化编写Java代码? 其中最重要的几点当属: 提高代码性能 使代码远离Bug 令代码更优雅 浩说在这里为大家整理14条yyds编码规范 记得 分享收藏 给需要的他哦 一、MyBatis不要为了多个查询条件而写11 【此有争议,大家对于此的多数验证是未受影响,大家在开发中各取所需,仅持指导性意见】 当遇到多个查询条件,使用where11可以很方便的解决我们的问题,但是这样很可能会造成非常大的性能损失,因为添加了where11的过滤条件之后,数据库系统就无法使用索引等查询优化策略,数据库系统将会被迫对每行数据进行扫描(即全表扫描)以比较此行是否满足过滤条件,当表中的数据量较大时查询速度会非常慢;此外,还会存在SQL注入的风险。 反例:selectidqueryBookInfoparameterTypecom。tjt。platform。entity。BookInforesultTypejava。lang。Integerselectcount()fromtruleBookInfotwhere11iftesttitle!nullandtitle!ANDtitle{title}ififtestauthor!nullandauthor!ANDauthor{author}ifselect 正例:selectidqueryBookInfoparameterTypecom。tjt。platform。entity。BookInforesultTypejava。lang。Integerselectcount()fromtruleBookInfotwhereiftesttitle!nullandtitle!title{title}ififtestauthor!nullandauthor!ANDauthor{author}ifwhereselect UPDATE操作也一样,可以用标记代替11。 二、迭代entrySet()获取Map的key和value 当循环中只需要获取Map的主键key时,迭代keySet()是正确的;但是,当需要主键key和取值value时,迭代entrySet()才是更高效的做法,其比先迭代keySet()后再去通过get取值性能更佳。 反例:Map获取value反例:HashMapString,StringmapnewHashMap();for(Stringkey:map。keySet()){Stringvaluemap。get(key);} 正例:Map获取keyvalue正例:HashMapString,StringmapnewHashMap();for(Map。EntryString,Stringentry:map。entrySet()){Stringkeyentry。getKey();Stringvalueentry。getValue();} 三、使用Collection。isEmpty()检测空 使用Collection。size()来检测是否为空在逻辑上没有问题,但是使用Collection。isEmpty()使得代码更易读,并且可以获得更好的性能;除此之外,任何Collection。isEmpty()实现的时间复杂度都是O(1),不需要多次循环遍历,但是某些通过Collection。size()方法实现的时间复杂度可能是O(n)。O(1)纬度减少循环次数例子 反例:LinkedListObjectcollectionnewLinkedList();if(collection。size()0){System。out。println(collectionisempty。);} 正例:LinkedListObjectcollectionnewLinkedList();if(collection。isEmpty()){System。out。println(collectionisempty。);}检测是否为null可以使用CollectionUtils。isEmpty()if(CollectionUtils。isEmpty(collection)){System。out。println(collectionisnull。);} 四、初始化集合时尽量指定其大小 尽量在初始化时指定集合的大小,能有效减少集合的扩容次数,因为集合每次扩容的时间复杂度很可能时O(n),耗费时间和性能。 反例:初始化list,往list中添加元素反例:int〔〕arrnewint〔〕{1,2,3,4};ListIntegerlistnewArrayList();for(inti:arr){list。add(i);} 正例:初始化list,往list中添加元素正例:int〔〕arrnewint〔〕{1,2,3,4};指定集合list的容量大小ListIntegerlistnewArrayList(arr。length);for(inti:arr){list。add(i);} 五、若需频繁调用Collection。contains方法则使用Set 在Java集合类库中,List的contains方法普遍时间复杂度为O(n),若代码中需要频繁调用contains方法查找数据则先将集合list转换成HashSet实现,将O(n)的时间复杂度将为O(1)。 反例:频繁调用Collection。contains()反例ListObjectlistnewArrayList();for(inti0;iInteger。MAXVALUE;i){时间复杂度为O(n)if(list。contains(i))System。out。println(listcontainsi);} 正例:频繁调用Collection。contains()正例ListObjectlistnewArrayList();SetObjectsetnewHashSet();for(inti0;iInteger。MAXVALUE;i){时间复杂度为O(1)if(set。contains(i)){System。out。println(listcontainsi);}} 六、使用静态代码块实现赋值静态成员变量 对于集合类型的静态成员变量,应该使用静态代码块赋值,而不是使用集合实现来赋值。 反例:赋值静态成员变量反例privatestaticMapString,IntegermapnewHashMapString,Integer(){{map。put(Leo,1);map。put(Familyloving,2);map。put(Coldontheoutsidepassionateontheinside,3);}};privatestaticListStringlistnewArrayList(){{list。add(Sagittarius);list。add(Charming);list。add(Perfectionist);}}; 正例:赋值静态成员变量正例privatestaticMapString,IntegermapnewHashMapString,Integer();static{map。put(Leo,1);map。put(Familyloving,2);map。put(Coldontheoutsidepassionateontheinside,3);}privatestaticListStringlistnewArrayList();static{list。add(Sagittarius);list。add(Charming);list。add(Perfectionist);} 七、工具类中屏蔽构造函数 工具类是一堆静态字段和函数的集合,其不应该被实例化;但是,Java为每个没有明确定义构造函数的类添加了一个隐式公有构造函数,为了避免不必要的实例化,应该显式定义私有构造函数来屏蔽这个隐式公有构造函数。 反例:publicclassPasswordUtils{工具类构造函数反例privatestaticfinalLoggerLOGLoggerFactory。getLogger(PasswordUtils。class);publicstaticfinalStringDEFAULTCRYPTALGOPBEWithMD5AndDES;publicstaticStringencryptPassword(StringaPassword)throwsIOException{returnnewPasswordUtils(aPassword)。encrypt();} 正例:publicclassPasswordUtils{工具类构造函数正例privatestaticfinalLoggerLOGLoggerFactory。getLogger(PasswordUtils。class);定义私有构造函数来屏蔽这个隐式公有构造函数privatePasswordUtils(){}publicstaticfinalStringDEFAULTCRYPTALGOPBEWithMD5AndDES;publicstaticStringencryptPassword(StringaPassword)throwsIOException{returnnewPasswordUtils(aPassword)。encrypt();} 八、删除多余的异常捕获并抛出 用catch语句捕获异常后,若什么也不进行处理,就只是让异常重新抛出,这跟不捕获异常的效果一样,可以删除这块代码或添加别的处理。 反例:多余异常反例privatestaticStringfileReader(StringfileName)throwsIOException{try(BufferedReaderreadernewBufferedReader(newFileReader(fileName))){Stringline;StringBuilderbuildernewStringBuilder();while((linereader。readLine())!null){builder。append(line);}returnbuilder。toString();}catch(Exceptione){仅仅是重复抛异常未作任何处理throwe;}} 正例:多余异常正例privatestaticStringfileReader(StringfileName)throwsIOException{try(BufferedReaderreadernewBufferedReader(newFileReader(fileName))){Stringline;StringBuilderbuildernewStringBuilder();while((linereader。readLine())!null){builder。append(line);}returnbuilder。toString();删除多余的抛异常,或增加其他处理:catch(Exceptione){returnfileReaderexception;}}} 九、字符串转化使用String。valueOf(value)代替value 把其它对象或类型转化为字符串时,使用String。valueOf(value)比value的效率更高。 反例:把其它对象或类型转化为字符串反例:intnum520;valueStringstrLovenum; 正例:把其它对象或类型转化为字符串正例:intnum520;String。valueOf()效率更高StringstrLoveString。valueOf(num); 十、避免使用BigDecimal(double) BigDecimal(double)存在精度损失风险,在精确计算或值比较的场景中可能会导致业务逻辑异常。 反例:BigDecimal反例BigDecimalbigDecimalnewBigDecimal(0。11D); 正例:BigDecimal正例BigDecimalbigDecimal1bigDecimal。valueOf(0。11D); 图1。失去精度 十一、返回空数组和集合而非null 若程序运行返回null,需要调用方强制检测null,否则就会抛出空指针异常;返回空数组或空集合,有效地避免了调用方因为未检测null而抛出空指针异常的情况,还可以删除调用方检测null的语句使代码更简洁。 反例:返回null反例publicstaticResult〔〕getResults(){returnnull;}publicstaticListResultgetResultList(){returnnull;}publicstaticMapString,ResultgetResultMap(){returnnull;} 正例:返回空数组和空集正例publicstaticResult〔〕getResults(){returnnewResult〔0〕;}publicstaticListResultgetResultList(){returnCollections。emptyList();}publicstaticMapString,ResultgetResultMap(){returnCollections。emptyMap();} 十二、优先使用常量或确定值调用equals方法 对象的equals方法容易抛空指针异常,应使用常量或确定有值的对象来调用equals方法。 反例:调用equals方法反例privatestaticbooleanfileReader(StringfileName)throwsIOException{可能抛空指针异常returnfileName。equals(Charming);} 正例:调用equals方法正例privatestaticbooleanfileReader(StringfileName)throwsIOException{使用常量或确定有值的对象来调用equals方法returnCharming。equals(fileName);或使用:java。util。Objects。equals()方法returnObjects。equals(Charming,fileName);} 十三、枚举的属性字段必须是私有且不可变 枚举通常被当做常量使用,如果枚举中存在公共属性字段或设置字段方法,那么这些枚举常量的属性很容易被修改;理想情况下,枚举中的属性字段是私有的,并在私有构造函数中赋值,没有对应的Setter方法,最好加上final修饰符。 反例:publicenumSwitchStatus{枚举的属性字段反例DISABLED(0,禁用),ENABLED(1,启用);publicintvalue;privateStringdescription;privateSwitchStatus(intvalue,Stringdescription){this。valuevalue;this。descriptiondescription;}publicStringgetDescription(){returndescription;}publicvoidsetDescription(Stringdescription){this。descriptiondescription;}} 正例:publicenumSwitchStatus{枚举的属性字段正例DISABLED(0,禁用),ENABLED(1,启用);final修饰privatefinalintvalue;privatefinalStringdescription;privateSwitchStatus(intvalue,Stringdescription){this。valuevalue;this。descriptiondescription;}没有Setter方法publicintgetValue(){returnvalue;}publicStringgetDescription(){returndescription;}} 十四、tring。split(Stringregex)部分关键字需要转译 使用字符串String的plit方法时,传入的分隔字符串是正则表达式,则部分关键字(比如。〔〕()等)需要转义。 反例:String。split(Stringregex)反例String〔〕splita。ab。abc。split(。);System。out。println(Arrays。toString(split));结果为〔〕String〔〕split1aababc。split();System。out。println(Arrays。toString(split1));结果为〔a,,a,b,,a,b,c〕 正例:String。split(Stringregex)正例。需要转译String〔〕split2a。ab。abc。split(。);System。out。println(Arrays。toString(split2));结果为〔a,ab,abc〕需要转译String〔〕split3aababc。split();System。out。println(Arrays。toString(split3));结果为〔a,ab,abc〕 图2。String。split(Stringregex)正反例 有帮助的话分享给你的小伙伴吧 也许他正需要 关注我 你会学到更多!