Ответ сильно зависит от используемой вами виртуальной машины Java. Я написал тестовую программу, просто чтобы получить некоторые цифры для JVM 1.8.0_05 (да, он старый; -):
import java.lang.reflect.Method;
public class ReflectionAccessTest {
public final static void main(String[] args) throws Exception {
for (int i = 0; i < 100000; i++) {
// do some "training"
ReflectionTarget.class.getMethod("a", Integer.TYPE, Integer.TYPE);
ReflectionTarget.class.getMethod("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", Integer.TYPE, Integer.TYPE);
ReflectionTarget.class.getMethod("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", Integer.TYPE, Integer.TYPE);
}
Method method = null;;
long start;
start = System.currentTimeMillis();
for (int i = 0; i < 10000000; i++) {
// do some "training"
method = ReflectionTarget.class.getMethod("a", Integer.TYPE, Integer.TYPE);
}
System.out.println("Time to get method with short name " + (System.currentTimeMillis() - start) + " ms");
start = System.currentTimeMillis();
for (int i = 0; i < 10000000; i++) {
method.invoke(null, Integer.MAX_VALUE, Integer.MIN_VALUE);
}
System.out.println("Time to execute method with short name " + (System.currentTimeMillis() - start) + " ms");
start = System.currentTimeMillis();
for (int i = 0; i < 10000000; i++) {
// do some "training"
method = ReflectionTarget.class.getMethod("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", Integer.TYPE, Integer.TYPE);
}
System.out.println("Time to get method with medium name " + (System.currentTimeMillis() - start) + " ms");
start = System.currentTimeMillis();
for (int i = 0; i < 10000000; i++) {
method.invoke(null, Integer.MAX_VALUE, Integer.MIN_VALUE);
}
System.out.println("Time to execute method with medium name " + (System.currentTimeMillis() - start) + " ms");
start = System.currentTimeMillis();
for (int i = 0; i < 10000000; i++) {
// do some "training"
method = ReflectionTarget.class.getMethod("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", Integer.TYPE, Integer.TYPE);
}
System.out.println("Time to get method with long name " + (System.currentTimeMillis() - start) + " ms");
start = System.currentTimeMillis();
for (int i = 0; i < 10000000; i++) {
method.invoke(null, Integer.MAX_VALUE, Integer.MIN_VALUE);
}
System.out.println("Time to execute method with long name " + (System.currentTimeMillis() - start) + " ms");
}
private static class ReflectionTarget {
public static void a(int a, int b) {
// do nothing
}
public static void aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(int a, int b) {
// do nothing
}
public static void aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(int a, int b) {
// do nothing
}
}
}
Вывод выглядит следующим образом:
Time to get method with short name 1012 ms
Time to execute method with short name 58 ms
Time to get method with medium name 3690 ms
Time to execute method with medium name 177 ms
Time to get method with long name 6279 ms
Time to execute method with long name 180 ms
Время на самом деле зависит от длины имени (это меня сначала удивило, но с другой стороны, это очевидно, потому что должен быть какой-то тест на равенство, который зависит от длины).
Но вы также можете видеть, что воздействие незначительно. Вызов getMethod
занимает 0,1 наносекунды для метода с именем, содержащим только один символ, и 0,6 наносекунды для метода с сумасшедшим длинным именем (не считая число a
с).
Если это различие действительно актуально для вас, вы можете попробовать механизмы кэширования полученного вами метода. Но в зависимости от времени, которое занимает вызываемый метод, это может быть совершенно бесполезно, если время его выполнения также не находится в диапазоне суб-наносекунд.