Я видел другие потоки, которые говорили, что производительность отражения java в 10-100 раз ниже, чем при использовании вызовов без отражения.
Мои тесты в 1.6 показали, что это не так, но я обнаружил некоторые другие интересные вещи, которые мне нужно, чтобы кто-то объяснил мне.
У меня есть объекты, которые реализуют мой интерфейс. Я сделал три вещи: 1) используя ссылку на объект, я привел этот объект к интерфейсу и вызвал метод через интерфейс 2) используя ссылку на реальный объект, вызвал метод напрямую и 3) вызвал метод через отражение. Я видел, что интерфейсный вызов # 1 был самым быстрым, за которым следовало отражение # 3, но я заметил, что прямой вызов метода был самым медленным с хорошим запасом.
Я не понимаю, я бы ожидал, что прямой вызов будет самым быстрым, затем интерфейс, затем отражение будет намного медленнее.
Blah и ComplexClass находятся в пакете, отличном от основного класса, и оба имеют метод doSomething (int x), который реализует интерфейс и просто печатает целое число x.
Вот мои результаты (времена в мс, результаты очень похожи с несколькими испытаниями):
Вызов метода напрямую: 107194
вызов метода непосредственно из объекта, приведенного к интерфейсу: 89594
вызов метода через отражение: 90453
Вот мой код:
public class Main
{
/**
* @param args the command line arguments
*/
public static void main(String[] args)
{
Blah x = new Blah();
ComplexClass cc = new ComplexClass();
test((Object) x, cc);
}
public static void test(Object x, ComplexClass cc)
{
long start, end;
long time1, time2, time3 = 0;
int numToDo = 1000000;
MyInterface interfaceClass = (MyInterface) x;
//warming up the cache
for (int i = 0; i < numToDo; i++)
{
cc.doSomething(i); //calls a method directly
}
start = System.currentTimeMillis();
for (int i = 0; i < numToDo; i++)
{
cc.doSomething(i); //calls a method directly
}
end = System.currentTimeMillis();
time1 = end - start;
start = System.currentTimeMillis();
for (int i = 0; i < numToDo; i++)
{
interfaceClass.doSomething(i); //casts an object to an interface then calls the method
}
end = System.currentTimeMillis();
time2 = end - start;
try
{
Class xClass = x.getClass();
Class[] argTypes =
{
int.class
};
Method m = xClass.getMethod("doSomething", argTypes);
Object[] paramList = new Object[1];
start = System.currentTimeMillis();
for (int i = 0; i < numToDo; i++)
{
paramList[0] = i;
m.invoke(x, paramList); //calls via reflection
}
end = System.currentTimeMillis();
time3 = end - start;
} catch (Exception ex)
{
}
System.out.println("calling a method directly: " + time1);
System.out.println("calling a method directly from an object cast to an interface: " + time2);
System.out.println("calling a method through reflection: " + time3);
}