Java的动态性支持学习四 反射调用的性能对比

Java的动态性支持学习一 - 反射机制 概念概述
Java的动态性支持学习二 - 反射机制 属性、方法、对象的操作
Java的动态性支持学习三 - 反射机制 取消属性、方法、构造器的访问限制
Java的动态性支持学习四 - 反射调用的性能对比
Java的动态性支持学习五 - 方法句柄 概念和句柄类型
Java的动态性支持学习六 - 方法句柄 获取和调用
Java的动态性支持学习七 - 方法句柄调用的性能对比

反射虽然强大,但存在性能的不足,使用反射基本上是一种解释操作,您可以告诉JVM您希望做什么并且它满足您的要求。曾经看过一本书举例说调用同一个方法,使用反射来动态实现比直接在源代码中编写的方式大概慢一到两个数量级。或许方法比较快些,但经过测试发现字段更慢。

测试Demo如下:

package net.oseye;
import java.lang.reflect.Field;

public class ReflectTest {
	//直接调用
	public static int numAdd(int loops){
		int val=0;
		long startTime=0;
		for(int i=0;i<loops;i++){
			if(i==0){startTime=System.nanoTime();}
			val+=i;
		}
		long totalTime=System.nanoTime()-startTime;
		System.out.println("直接调用总的纳秒时间:\t\t"+totalTime);
		return val;
	}
	//引用调用字段
	public static int numAddReference(int loops){
		User user=new User();
		long startTime=0;
		for(int i=0;i<loops;i++){
			if(i==0){startTime=System.nanoTime();}
			user.num+=i;
		}
		long totalTime=System.nanoTime()-startTime;
		System.out.println("引用调用字段总的纳秒时间:\t"+totalTime);
		return user.num;
	}
	//反射调用字段
	public static int numAddReflection(int loops) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException{
		User user=new User();
		long startTime=0;
		for(int i=0;i<loops;i++){
			if(i==0){startTime=System.nanoTime();}
			Class<?> cUser=user.getClass();
			Field field=cUser.getField("num");
			field.set(user, field.getInt(user)+i);
		}
		long totalTime=System.nanoTime()-startTime;
		System.out.println("反射调用字段总的纳秒时间:\t"+totalTime);
		return user.num;
	}
	
	public static void main(String[] args) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException{ 
		int loops=1000000;
		numAdd(loops);
		numAddReference(loops);
		numAddReflection(loops);
	}
}
class User{
	public int num;
}

输出:

直接调用总的纳秒时间:	4784726
引用调用字段总的纳秒时间:	26341772
反射调用字段总的纳秒时间:	2707670627

测试100万次,除掉第一次的时间,可以看出反射用的时间是引用的100倍,是直接调用的500多倍。当然根据测试的次数不同,机器的配置不同,结果稍有不同。

原文地址:https://www.cnblogs.com/zhaiqianfeng/p/4618324.html