目录
1.Exceptional return value of java.io.File.delete() ignored
2.Result of integer multiplication cast to long
3.Return value of Throwable.getMessage() ignored, but method has no side effect
4.Dead store to local variable
5.Redundant nullcheck of lineB, which is known to be non-null
6.Exception is caught when Exception is not thrown
7.循环体内,字符串的联接方式,使用StringBuilder的append方法进行扩展。
9.Found reliance on default encoding: String.getBytes()(发现对默认编码的依赖:String.getBytes())
12.May expose internal representation by returning reference to mutable object
13.Possible null pointer dereference of List
26.拒绝服务:StringBuilder或者StringBuffer*
28.在JAVA EE程序中直接使用Socket进行通信容易出错。
30.一级类:代码质量 二级类:使用equals()来判断字符串是否为空
35.Optional没有在调用isPresent()后访问值
39.请使用System.currentTimeMillis()代替new Date().getTime()
40.事务场景中,抛出异常被catch后,如果需要回滚,一定要手动回滚事务。
命名规范和注释
类、类属性、类方法的注释必须使用javadoc规范,使用/*内容/格式,不得使用//xxx方式和/xxx/方式
,除常用方法(如getXxx/isXxx)等外,不要在条件判断中执行复杂的语句,
方法内部单行注释,在被注释语句上方另起一行,所有的抽象方法(包括接口中的方法)必须要用javadoc注释、除了返回值、参数、异常说明外
1.Exceptional return value of java.io.File.delete() ignored
问题原因:java.io.File.delete()返回值未接受
规范写法:接受返回值并判断是否操作成功
2.Result of integer multiplication cast to long
问题原因:上面那行代码存在溢出风险在java中,int * int的结果还是int类型,不会自动转换为long类型,而long * int的结果是long类型,结果不会溢出
规范写法:将int * int换成long * int结果不会溢出
long size = quotaSize * 1024 * 1024; 换成 long size = quotaSize * 1024L * 1024;
3.Return value of Throwable.getMessage() ignored, but method has no side effect
问题原因:抛异常不合规范
规范写法:改为logger.error
4.Dead store to local variable
问题原因:局部变量的死存储,调用的方法有返回值并接受但是没有使用
规范写法:改为只调用方法不接受返回值
5.Redundant nullcheck of lineB, which is known to be non-null
问题原因:行C的冗余空检查,已知为非空
规范写法:多余的空判断去掉
数据库查询返回的list和set时查询结果为空也会不返回null 所以无需进行list != null 或 set != null 判断
6.Exception is caught when Exception is not thrown
问题原因:try{}catch(){}代码块中没有需要catch的Exception 类
规范写法:根据需要将代码的逻辑中不需要的try{}catch(){}去掉
7.循环体内,字符串的联接方式,使用StringBuilder的append方法进行扩展。
原因:下面代码,反编译出得字节码文件显示每次循环都会new出一个StringBuilder对象,然后进行append操作最后通过toString()方法返回String对象,造成资源的浪费
String str = "string" for(int i = 0; i < 10; i++){ str = str + "string"; } //反编译之后大致这样子 String str = "string" for(int i = 0; i < 10; i++){ str = (new StringBuilder()).append(str).append("string").toString(); } //string对象不可变,这里是在不断地创建StringBuilder对象,然后又调用tostring方法转成string对象。也就是在StringBuilder和string当中不断转化,这个过程是一个消耗。主要是当循环次数比较多的时候,就会在内存中创建很多StringBuilder对象,虽然会自动gc,但是这也增加了GC次数,然后就会有stop the world。减少吞吐量,增加了延时。
规范写法:使用StringBuild的append拼接字符串
String str = "string" StringBuilder strb = new StringBuilder(str); for(int i = 0; i < 10; i++){ strb.append("string"); } str = strb.toString();
8.关于基本数据类型与包装数据类型的使用标准如下:
1) 所有的POJO类属性必须使用包装数据类型。 2) RPC方法的返回值和参数必须使用包装数据类型。
原因:POJO 类属性没有初值是提醒使用者在需要使用时,必须自己显式地进行赋值,任何 NPE 问题,或者入库检查,都由使用者来保证。数据库的查询结果可能是 null,因为自动拆箱,用基本数据类型接收有 NPE 风险。
3) 所有的局部变量推荐使用基本数据类型。
原因:Java中共有三种变量,分别是类变量、成员变量和局部变量。他们分别存放在JVM的方法区、堆内存和栈内存中。 其中局部变量的作用域只在方法内部。那么,既然是一个作用域只在方法内的变量,不需要考虑那么多,怎么性能高就怎么定义。
在Java语言中,new一个对象是存储在堆里的,我们通过栈中的引用来使用这些对象。所以,对象本身来说是比较消耗资源的。
对于经常用到的类型,如int等,如果我们每次使用这种变量的时候都需要new一个Java对象的话,就会比较笨重。而基本数据类型的变量不需要使用new创建,它们不会在堆上创建,而是直接在栈内存中存储,因此会更加高效。
9.Found reliance on default encoding: String.getBytes()(发现对默认编码的依赖:String.getBytes())
原因:对默认编码依赖会因为对系统的默认编码不可预期而出现问题
改正:避免出现问题最好还是还是将默认编码指定好,如
String.getBytes("GBK");
10.Map遍历时候entryset比keyset效率高
原因:因为使用keySet遍历时,当使用key值取得Map中的Value时,Map又遍历了一遍。而EntrySet时,由于EntrySet本身就是key-value结构,所以直接将Map的key-value给取出来了,自然速度就要快上一些,使用迭代器会更快一些。
改正:使用entryset替换keyset
//keyset使用for循环遍历 for(String key : map.keySet()){ map.get(key); } //keyset使用迭代器遍历 Iterator<String> ito = mapInfo.keySet().iterator(); while(ito.hasNext()){ String key = it,next(); map.get(key); } //entryset替换后的for循环遍历 for(Map.Entry<String, String> entry : map.entrySet()){ entry.getValue(); } //entryset替换后的迭代器遍历 Iterator<Map.Entry<String, String>> ito = map.entrySet(); while(ito.hasNext()){ Map.Entry<String, String> entry = ito.next(); entry.getValue(); }
11.未使用的局部变量
原因:局部遍历未使用,资源浪费
改正:删除
public int test(){ //变量a未使用对功能无影响可以直接删除 int a = 1; int b = 3, c= 2; return b + c; }
12.May expose internal representation by returning reference to mutable object
原因:返回对存储在对象字段中的可变对象值的引用,将公开对象的内部表示形式。如果实例由不受信任的代码访问,并且对可变对象的未经检查的更改将损害安全性或其他重要属性,则需要采取不同的措施。在许多情况下,返回对象的新副本是更好的方法。(引用类型的可变对象都会有这种风险)
改正:方法如下
//修改前的实体类(lombok的@Data也是这种get和set的写法) public class clonecc { private Date date; private List list; public clonecc(Date date, List list) { this.date = date; this.list = list; } public List getList() { return list; } public void setList(List list) { this.list = list; } public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } } //修改前的测试类 public class testr { public static void main(String[] args) throws Exception { Date date = new Date(); String string = "aaaa"; ArrayList<String> list = new ArrayList<>(); list.add("1"); list.add("2"); clonecc clonecc = new clonecc(date,list,string); clonecc.setDate(date); System.out.println(clonecc.getDate()); date.setTime(6); System.out.println(clonecc.getDate()); clonecc.setList(list); System.out.println(clonecc.getList()); list.add("3"); System.out.println(clonecc.getList()); } } 结果:修改list和date影响实体类中属性的值了在代码中是存在风险的 Thu Dec 08 17:34:22 CST 2022 Thu Jan 01 08:00:00 CST 1970 [1, 2] [1, 2, 3] //修改后的实体类 public class clonecc { private Date date; private List list; public clonecc(Date date, List list) { if(date != null) { this.date = (Date) date.clone(); }else { this.date = null; } this.list = list; } public List getList() { return list; } public void setList(List list) { this.list = list; } public Date getDate() { if(this.date != null) { return (Date) date.clone(); }else { return null; } } public void setDate(Date date) { if(date != null) { this.date = (Date) date.clone(); }else { this.date = null; } } //修改后的测试方法 public class testr { public static void main(String[] args) throws Exception { Date date = new Date(); String string = "aaaa"; ArrayList<String> list = new ArrayList<>(); list.add("1"); list.add("2"); clonecc clonecc = new clonecc(date,list,string); clonecc.setDate(date); System.out.println(clonecc.getDate()); date.setTime(6); System.out.println(clonecc.getDate()); clonecc.setList((List) list.clone()); System.out.println(clonecc.getList()); list.add("3"); System.out.println(clonecc.getList()); } } 结果:修改list和date没有影响实体类的属性 Thu Dec 08 17:28:54 CST 2022 Thu Dec 08 17:28:54 CST 2022 [1, 2] [1, 2]
13.Possible null pointer dereference of List
问题原因:在编程中使用方法返回的list或者声明的list进行流处理等操作时要对其判空处理否则会报NEP异常(