java反射如何提升性能
Java应用反射的时候,性能往往是java程序员担心的地方,那么在大量运用反射的时候,性能的微弱提升,对这个系统而言都是如旱地逢甘霖。
下面用代码简单验证一下反射性能都损耗在哪里。
package littlehow.reflect.demo;
/**
* WorkBean 作为反射性能测试的bean
*
* @author littlehow
* @time 2016-06-13 14:27
*/
public class WorkBean {
/**
* 工作人名称
*/
private String userName;
/**
* 公司名称
*/
private String companyName;
/**
* 工作年限
*/
private int workAge;
/**
* 薪资待遇
*/
private double salary;
/**
* 无参构造
*/
public WorkBean() {
super();
}
/**
* 姓名
* @param userName
*/
public WorkBean(String userName) {
this.userName = userName;
}
/**
* 姓名和公司名称的构造
* @param userName
* @param companyName
*/
public WorkBean(String userName, String companyName) {
this(userName);
this.companyName = companyName;
}
/**
* 工作
*/
public void workAt(boolean flag) {
System.out.println(this.userName+"在"+(flag?"上午":"下午")+"上午工作的时候一直在打瞌睡!");
}
/**
* 工作
* @param flag
* @param message
*/
public void workAt(boolean flag, String message) {
System.out.println(this.userName+"在"+(flag?"上午":"下午")+message);
}
/**
* 工作
*/
public void workAt() {
System.out.println(this.userName+"工作了好久了");
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getCompanyName() {
return companyName;
}
public void setCompanyName(String companyName) {
this.companyName = companyName;
}
public int getWorkAge() {
return workAge;
}
public void setWorkAge(int workAge) {
this.workAge = workAge;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
@Override
public String toString() {
return this.userName + "在" + this.companyName + "工作了" + this.workAge + "年,现在的薪水是" + this.salary;
}
}
然后是测试反射的demo
package littlehow.reflect.demo;
import org.junit.Test;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* ReflectDemo 反射性能消耗在哪里
*
* @author littlehow
* @time 2016-06-13 14:41
*/
public class ReflectDemo {
/**
* 测试class
*/
static Class<?> clazz = WorkBean.class;
/**
* 公用构造方法缓存
*/
private static final HashMap<String, Constructor<?>> constructors = new HashMap<String, Constructor<?>>();
/**
* 公用method缓存
*/
private static final ConcurrentHashMap<String, MethodCache> methods = new ConcurrentHashMap<String, MethodCache>();
/**
* 不经过优化的构造方法性能测试
*/
@Test
public void constructorNormalTest() {
long start = System.currentTimeMillis();
try {
Object obj = null;
for(int i = 0; i < 1000000; i ++) {
Constructor<?> cons1 = clazz.getConstructor();
obj = cons1.newInstance();
Constructor<?> cons2 = clazz.getConstructor(String.class);
obj = cons2.newInstance("littlehow");
Constructor<?> cons3 = clazz.getConstructor(String.class, String.class);
obj = cons3.newInstance("littlehow", "future company");
}
System.out.println(obj);//littlehow在future company工作了0年,现在的薪水是0.0
} catch (Exception e) {
e.printStackTrace();
}
long end = System.currentTimeMillis();
System.out.println("use time : " + (end - start) + "ms");//平均840毫秒左右
}
/**
* 对单一的进行缓存,速度最快,但功用性不够好
* 相对于
* @see constructorNormalTest()方法,性能提升10倍
* 可见反射中对构造方法的获取非一个非常耗时的操作
*/
@Test
public void constrctorBufferOne() {
long start = System.currentTimeMillis();
try {
Constructor<?> cons1 = clazz.getConstructor();
Constructor<?> cons2 = clazz.getConstructor(String.class);
Constructor<?> cons3 = clazz.getConstructor(String.class, String.class);
Object obj = null;
for(int i = 0; i < 1000000; i ++) {
obj = cons1.newInstance();
obj = cons2.newInstance("littlehow");
obj = cons3.newInstance("littlehow", "future company");
}
System.out.println(obj);//littlehow在future company工作了0年,现在的薪水是0.0
} catch (Exception e) {
e.printStackTrace();
}
long end = System.currentTimeMillis();
System.out.println("use time : " + (end - start) + "ms");//平均80毫秒左右
}
/**
* key值的计算耗时也比较大,可以再进行优化
* @param clazz
* @param arguClass
* @return
* @throws NoSuchMethodException
*/
private static Constructor<?> getConstrucor(Class<?> clazz, Class<?> ...arguClass) throws NoSuchMethodException {
String key = clazz.getName();
for (Class<?> argu : arguClass) {
key = key + argu.getName();//这里会有编译优化
}
Constructor<?> constructor = constructors.get(key);
if (constructor == null) {
constructor = clazz.getConstructor(arguClass);
constructors.put(key, constructor);
}
return constructor;
}
/**
* 公用缓存,在性能和开发维护中这种处理,在性能要求不是超高的
* 系统中可以选用该方式进行构造方法的缓存,提升开发速度
* 效率相对第一个测试性能也提升了一倍多
*/
@Test
public void constructorBufferAll() {
long start = System.currentTimeMillis();
try {
Constructor<?> cons1 = clazz.getConstructor();
Constructor<?> cons2 = clazz.getConstructor(String.class);
Constructor<?> cons3 = clazz.getConstructor(String.class, String.class);
Object obj = null;
for(int i = 0; i < 1000000; i ++) {
obj = getConstrucor(clazz).newInstance();
obj = getConstrucor(clazz, String.class).newInstance("littlehow");
obj = getConstrucor(clazz, String.class, String.class).newInstance("littlehow", "future company");
}
System.out.println(obj);//littlehow在future company工作了0年,现在的薪水是0.0
} catch (Exception e) {
e.printStackTrace();
}
long end = System.currentTimeMillis();
System.out.println("use time : " + (end - start) + "ms");//平均330毫秒左右
}
/**
* 用class直接newInstance
&nb