jvm性能调优(四)-----编写高效的java代码 构造器参数太多怎么办? 不需要实例化的类应该构造器私有 不要创建不必要的对象 避免使用终结方法 使类和成员的可访问性最小化 当心字符串连接的性能
可以使用建造者模式,代码示例如下:
public class FoodBuilder { //required private final String foodName; private final int reilang; //optional private int danbz; private int dianfen; private int zf; private int tang; private int wss; private FoodBuilder(Builder builder) { foodName = builder.foodName; reilang = builder.reilang; danbz = builder.danbz; //..... } public static class Builder{ //required private final String foodName; private final int reilang; //optional private int danbz; private int dianfen; private int zf; private int tang; private int wss; public Builder(String foodName, int reilang) { super(); this.foodName = foodName; this.reilang = reilang; } public Builder danbz(int val) { this.danbz = val; return this; } //....... public FoodBuilder build() { return new FoodBuilder(this); } } public static void main(String[] args) { FoodBuilder foodBuilder = new Builder("food2", 1000).danbz(100) //..... .build(); } }
不需要实例化的类应该构造器私有
对于很多工具类,提供的都是静态方法,需要将构造器私有化,例如jdk中的Arrays类
不要创建不必要的对象
先看一段代码:
public class Sum { public static void main(String[] args) { long start = System.currentTimeMillis(); Long sum = 0L;//对象 for(long i=0;i<Integer.MAX_VALUE;i++) { sum = sum+i; //new 20多亿的Long的实例 } System.out.println("spend time:"+(System.currentTimeMillis()-start)+"ms"); } }
运行结果:
代码修改下(将Long改成long):
public class Sum { public static void main(String[] args) { long start = System.currentTimeMillis(); long sum = 0L;//对象 for(long i=0;i<Integer.MAX_VALUE;i++) { sum = sum+i; //new 20多亿的Long的实例 } System.out.println("spend time:"+(System.currentTimeMillis()-start)+"ms"); } }
运行结果:
也就是说,在能用基本数据类型的时候就不要用对象,因为对象的创建、销毁(涉及到GC),会大大增加性能损耗。
避免使用终结方法
就是不要使用Object对象中的finalize方法
protected void finalize() throws Throwable { }
尤其是在这个方法里面写逻辑,例如回收资源等,因为虚拟机不保证这个方法能及时被执行,或者说被执行。
使类和成员的可访问性最小化
主要目的就是解耦。
当心字符串连接的性能
public class Test { private static class Log{ public static void debug(String msg){ if (isDebug()) System.out.println(msg); } public static boolean isDebug(){ return false; } } public static void main(String[] args) { int count = 10000000; long start = System.currentTimeMillis(); for(int i = 0;i<count;i++){ Log.debug("The system is running and the time is " +System.currentTimeMillis() +" now,Let's do another thing:"+System.nanoTime()); } System.out.println("直接打印模式,次数:"+count+":spend time :" +(System.currentTimeMillis()-start)+"ms"); start = System.currentTimeMillis(); for(int i = 0;i<count;i++){ if(Log.isDebug()) Log.debug("The system is running and the time is " +System.currentTimeMillis() +" now,Let's do another thing:"+System.nanoTime()); } System.out.println("先判断再打印模式,次数:"+count+":spend time :" +(System.currentTimeMillis()-start)+"ms"); } }
运行结果:
解释:上面的isDebug()一直返回的是false,所以下面一种写法不需要去拼接字符串,大大节省时间。这也是大部分开源框架(spring、mybatis等)打印日志前都会判断的一个原因。 并且如果字符串拼接过长的情况下,使用StringBuilder或StringBuffer。