性能调优-------(二)编写高质量代码151个建议

1、不要在变量和常量中出现混淆的代码
比如:long i=1l;会很容易看成11如果代码多的话。
2、不要让常量变成变量
public static final int a=new Random().nextInt();是不是很神奇,如果说static 和 final确定一个常量但是每次运行都不会知道常量是啥,所以一定要写死常量。
3、三木运算符在用的时候确保三元操作符类型一致,否则会基本类型自动转换
String s=String.valueOf(1<12?90:100);
String s1=String.valueOf(1<12?90:100.0);
System.out.println("ss1:"+ss1);
结果是false
4、避免带有长参数的方法重载(不要用就好了,因为java编译时候会很聪明也很懒)
public void calPrice(int price,int discount);
public void calPrice(int price,int… iscount);
5、别让null值和空值威胁到变长方法(如上不多说)
6、重写变长方法循规蹈矩(如上不多说)
7、警惕自增的陷阱
java中int count=0;for(int i=0;i<10;i++){
count=count++;
}
你可一猜测下count=10?中陷阱了,java和php语言中都是只能count++;原因是在编译的时候会首先将count放在临时变量区注意这个时候count=0返回的时候还是count=0,那么c++则可以这样使用。
8、不要让旧语法困扰自己,阅读明白就好
9、静态导入慎用(静态导入常量类和方法可以,禁止使用*否则之后机器可以解析但是编写程序和维护会出现问题)
10、不要在本类中覆盖静态导入的类和方法(否则java有个最短路径概念找到最容易找到的类导致结果就是可能你没有拿到你想要的数据)
11、养成良好习惯,显示声明UID
类实现Serializable接口的目的是为了可持久化,比如网络传输或者本地存储为系统的分布和异构部署提供先决支持条件,若没有序列化,远程调用和对象数据库则不可能存在。
为什么要这样,因为我们在读写的时候用到了序列化和反序列化,如果序列化和反序列化不一致,反序列化会报InvalidClassException异常,原因是对应的版本不对,jvm就不能把数据流转换为实例,那么根据什么来判断版本就是UID…private static final long serialVersionUID = 1L;如果有新需求变更及时更改版本号
12、避免用序列化类在构造函数中为不变量赋值
反序列化时候构造函数不会执行,所以如果将常量赋值在构造函数中且序列化版本号没有及时变更,那么结果还是原来第一次版本的结果。
13、避免为final变量复杂赋值
总结:反序列化时候final在一下情况不会被重新赋值
构造函数为final变量赋值
通过方法返回值为final变量赋值
final修饰的属性不是基本类型
14、使用序列化类的私有方法巧妙解决部分属性持久化问题
部分属性持久化可以通过transient关键字解决
15、break万万不可以忘记
16、易变业务使用脚本语言编写
17、慎用动态编译
在框架中慎用、在要求高性能的项目中慎用、要考虑安全问题
记录动态编译过程
18、避免instanceof非预期结果
instanceof是一个简单的二元操作符,它是用来判断一个对象是否是一个类实例的其操作非常简单
instanceof只能用于对象的判断,不能用于基本类型的判断
19、断言绝对不是鸡肋
assert默认不启用,抛出异常AssertionError是继承Error
以下时候不可以使用:方法对外公开的时候,在执行逻辑代码的情况
私有方法可以使用,流程控制不能到达区域也可以使用,建立程序探针时候
20、不要只替换一个类
发布时候最好整体war包发布,禁止使用类文件替换方式
第二章、基本类型
21、用偶判断,不用奇判断
对于基础知识我们应该知其然并要知其所以然
22、用整数类型处理货币
金融方面的最好使用BigDecimal专门为弥补浮点数无法精确计算设计的而且符合与数据库映射
最优的解决方案,或者使用整型时候使小数扩大100倍缩小100倍非金融行业用的多。
23、不要让类型默默转换
24、边界校验
高手可以将前台的校验统统解除,所以前后台都要校验
25、不要让四舍五入亏了
对于参与银行的话java 支持以下七种舍入方式:使用RoundingMode设置就可以
ROUND_UP:远离零方向舍入。
ROUND_DOWN:趋向零方向舍入
ROUND_CEILING:向正无穷舍入
ROUND_FLOOR:向负无穷舍入
HALF_UP:最近数字舍入(5进)
HALF_DOWN:最近数字舍入(5舍)
HALF_EVEN:银行家算法
普通项目中直接使用Math.round方法就可以
26、堤防包装类型的null值
27、小心包装类型的大小比较
28、优先使用整型池
使用Integer.valueOf()的时候自动装箱和拆箱过程中是有个范围的-128到127假如在此区间则获得对象是同一个,假如超过该数字,则需要重新new一个
29、优先选择基本类型
30、不要随便设置随机数
第三章、类对象及方法
31、在接口中不要存在实现代码
不要慌接口中可以根据匿名实现代码
32、静态变量一定要先申明后赋值
33、不要重写静态方法
34、构造函数尽量简化
35、避免在构造函数中初始化其他类
36、使用构造代码块精炼程序
代码块四种:普通代码块、静态代码块、同步代码块、构造代码块
37、构造代码块会想你所想
38、使用静态内部类提高封装性
39、使用匿名类的构造函数
40、匿名类的构造函数很特殊
41、多重继承
如何实现很好实现,不要被单继承多实现迷惑了,那个写两个接口,再写该对应的实现类,然后用子类继承就哦了
42、工具类不可以实例化
43、避免对象的浅拷贝
类实现了Cloneable就具备了被拷贝能力,如果实现clone()方法就具备拷贝能力
拷贝规则注意:基本类型:如果变量是基本类型,则拷贝其值,比如int、float等
对象:如果变量是一个实例对象,则拷贝地址引用
String字符串:拷贝的是一个地址是个引用。在此处可将它看为基本类型
44、推荐使用序列化实现对象的拷贝
当然也可以使用反射
[图片]
记得实现序列版本号
45、重写equals方法(去掉空格trim)
46、equals考虑null值使用时候
47、equals中使用getClass进行类型判断
48、重写equals方法必须重写hashCode方法(HashCodeBuilder工具类拿来主义)
49、重写toString方法
50、使用package-info类为包服务
特性:不能随便被创建、服务的对象很特殊、不能有实现代码
不可以继承,不能有接口没有UML的六种关系
51、不要主动进行垃圾回收
第四章、字符串
52、推荐使用String直接量赋值(原因搞懂内存分析就知道了)
53、注意方法中传递的参数要求
54、正确使用String StringBuffer、StringBuilder
StringBuffer使用场景:xml解析、http参数解析和封装。
StringBuilder类场景、单线程、sql语句拼装json拼装
55、注意字符串的位置
在含有+表达式中,String字符串具有最高优先级
56、自由选择字符串拼接方法
concat或者append和+号,效率append最快concat是+号的两倍
57、在复杂的字符串操作中使用正则表达式
尽量不要用spilt
58、强烈建议UTF编码
59、对字符串排序持一种宽容的态度
如果排序不是一个关键算法,使用collator类即可
第四章、数组和集合
60、性能考虑、数组是首选
如果算法中算法如果是基本类型则使用数组效率最高,使用集合效率低点。
性能要求高的场景中使用数组替代集合
61、若有必要,使用变长数组
使用copyOf方法产生个新的长度
62、警惕数组的浅拷贝
63、在明确的场景下,为集合指定初始容量
64、非常有必要在集合初始化时候声明容量
65、多种最值算法,适时选择
66、避开基本类型数组转换列表陷阱
67、asList方法产生的List对象不可更改
68、不同的列表选择不同的遍历方法(性能要求高就用下标遍历吧比foreach性能高很多)
69、频繁插入和删除时候使用LinkedList
70、列表相等只需要关心元素数据
71、子列表只是原列表的一个视图
72、推荐使用subList处理局部列表
73、生成子列表后不要再操作原列表
74、使用Comparator进行排序
75、不推荐使用binarySearch对列表进行检索
但是从性能上binarySearch是最好的选择
76、集合中的元素必须要做到compareTo和equals同步
77、集合运算时使用更优雅的方式
list可以addAll(list2)合集也可以交集list。retainAll(list2)
list.removeAll(list2)
78、使用shuffle打乱列表
79、减少HashMap中元素的数量
80、集合中的哈希码不要重复
81、多线程使用Vector或者HashTable
82、非稳定排序推荐使用List
TreeSet适用于不变量的集合数据排序
StoredSet排序中元素被修改后可能会影响其排序位置
83、集合大家族
第六章、枚举和注解
84、推荐使用枚举定义常量
项目开发中推荐使用枚举类代替接口常量或者类常量
85、使用构造函数协助描述枚举项
86、小心switch带来的空值异常
87、在switch中default代码块增加AssertionError错误
88、使用valueOf前必须进行校验
89、用枚举实现工厂方法模式更简洁
90、枚举项的数量限制在64个以内
91、小心注解继承
92、枚举和注解结合使用威力更大
93、注意重写版本的区别
第七章、泛型和反射
94、java的泛型是类型擦除
95、不能初始化泛型参数和数组
96、强制声明泛型的实际类型
97、不同的场景使用不同的泛型通配符
98、警惕泛型是不能协变和逆变的
99、建议采用的顺序是List,List,List List确定的某一个类型,可以进行读写操作 List只读型一般用于返回值 List可以读写操作
100、严格建议限定泛型类型采用多重界限
101、数组的真实类型必须是泛型类型的子类型
102、注意Class类的特殊性
103、适时选择得到反射的属性和方法
104、反射访问属性和方法时候将Accessible设置为true
105、使用forName动态加载类文件
106、动态加载不适合数组
107、动态代理可以使用代理模式更加灵活
108、使用反射增加装饰模式的普遍适用性
109、反射可以使模板方法更好用
110、不考虑太多效率时候用反射
第八章、异常
111、提倡异常封装
112、采用异常链传递异常(责任链)
113、受检异常尽可能转化为非受检异常
114、不要在finally中处理返回值
115、不要再构造函数中抛出异常
116、使用Throwable获得栈信息
117、异常只为异常服务
118、多使用的异常先不要考虑性能了
第九章、多线程和并发
119、不推荐重写start方法
120、启动线程前stop方法是不可靠的
121、不使用stop方法停止线程
stop方法是过时的,stop方法会导致代码逻辑不完整,破坏原子逻辑
122、线程优先级只使用三个等级
java线程有10个级别准确的说11个jvm级别为0,应用程序不能设置
min_priority norm_priority max_priority
123、使用线程异常处理器提升系统可靠性
124、volatile不能保证数据同步
移植性差、误用多
125、异步运算考虑使用callable接口
类似于runable
126、优先选择线程池
127、实施时候选择不同线程池来实现
128、lock和synchronized是不同的
lock是无阻塞的,synchronized是阻塞锁
lock实现公平锁、synchronized是非公平锁
lock是代码级,synchronized是jvm级
两种不同机制,不同情况选择
129、预防线程死锁
130、适当设置阻塞队列长度
131、使用countDownLatch协调子线程
132、cyclicBarrier让多线程齐步走
第十章、性能和效率
133、提升java性能的基本方法
不要在循环条件中计算
尽可能把变量方法声明为final static
缩小变量的作用范围目的是有助于GC的回收
频繁字符串操作使用StringBuilder或者StringBuffer
使用非线性检索,使用binarySearch搜索时候,元素必须排序
否则准确度不高
重写exception的fillInStackTrace方法
不需要建立的对象就不建立
134、若非必要,不要克隆对象
克隆对象不比new的效率高
135、望闻问切的方式诊断性能
观察性能、
136、定义性能衡量标准
技术和业务之间的衡量、性能优化使技术优化的目标
137、解决首要系统性能问题
解决性能优化要单线程小步前进,避免关注点过多
138、调整jvm参数以提升性能
调整堆内存大小
第11章、开源项目
139、大胆采用开源工具
140、推荐使用Guava扩展工具包
141、Apache扩展包
142、推荐使用Joda日期时间包
143、可以选择多种Collections扩展
第12章、思想为源
144、提倡良好的代码风格
整洁、统一、流行、便捷
145、不要完全依靠单元测试来发现问题
146、注释正确、清晰、简洁
147、让接口的职责保持单一
148、增强类的可替换性
149、依赖抽象而不是实现
150、抛弃不良习惯
151、以技术自律
加群:300458205
以下是完整版文件链接

你可能感兴趣的:(职场@性能调优系列)