Оптимизирует ли Java поле, которое просто служит в качестве возвращаемого значения?
Почему я спрашиваю:
Я хотел бы знать, что на стороне компилятора происходит какая-либо оптимизация, которая сделает один или другой метод более предпочтительным. Так как я прочитал этот пост, Python не оптимизирует метод для более быстрой работы.
Пример:
Я объявил 2 метода, которые предоставляют одинаковое значение. Но barA
возвращает его через внутреннее объявление поля.
public class Foo {
public int barA(){
int a = 1;
return a;
}
public int barB(){
return 1;
}
}
Тесты:
public class TestFoo {
Foo foo = new Foo();
Method methodA = foo.getClass().getMethod("barA");
Method methodB = foo.getClass().getMethod("barB");
public TestFoo() throws NoSuchMethodException {
}
@Test
public void methodA() throws Exception {
assertTrue(Integer.TYPE.equals(methodA.getReturnType()));
}
@Test
public void methodB() throws Exception {
assertTrue(Integer.TYPE.equals(methodB.getReturnType()));
}
@Test
public void equalsSame() throws Exception{
assertEquals(foo.barA(), foo.barB());
}
}
Результаты, достижения:
Тесты показали, что я на самом деле имею дело с одним и тем же значением и типом возврата в обоих методах.
Отказ от ответственности: эта картинка не предназначена для выделения секундомера, junit запускается для каждого метода, так как он никак не связан с оптимизацией компилятора, о которой я спрашиваю.
Вопрос:
Пытается ли Java на самом деле оптимизировать ненужные объявления полей для более быстрого выполнения?
Я не смог найти вопрос, касающийся этого.
С помощью:
- JDK 1.8.0_121
- джунит 4.10
2 ответа
Учитывая обновления OP, реальный ответ здесь очень прост: java - это статически скомпилированный язык.
Подпись метода... это то, что говорит подпись. В подписи написано, что нужно вернуть значение типа int. И это то, что вернет любой метод с int на его сигнатуре. Ничто в архитектуре Java не позволяет вам динамически изменять такие вещи во время выполнения. С этой точки зрения все ваши тесты для возвращаемого типа являются поддельными. Конструкция языка подразумевает, что ответ всегда "метод возвращает int
, И обратите внимание: если тип возвращаемого значения будет ссылочным, скажем, Number
тогда, конечно, у вас может быть один метод, возвращающий экземпляр Long, а другой - объект Integer (приводящий к различным типам, но все же подтипам Number)!
Кроме того, ФП говорит о том, что нужно смотреть на разные времена исполнения.
Да, junit запускает секундомер, чтобы примерно сказать вам, как долго проходит каждый тест. Но это не измерение. Чтобы понять истинное влияние кода на производительность, вы должны сделать реальные измерения. С этой точки зрения: цифры от JUnit не означают того, что вы думаете, они имеют в виду. Они не являются подходящей основой для таких выводов.
Если мы возьмем пример:
class Main {
int foo() {
int i = 0;
return i;
}
int bar() {
return 0;
}
public static void main(String[] args) {
new Main().foo();
new Main().bar();
}
}
И просмотрите байт-код:
class my.pckage.Main extends java.lang.Object{
my.pckage.Main();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
int foo();
Code:
0: iconst_0 //push zero onto the stack
1: istore_1 //pop off the stack and store in local variable
2: iload_1 //load an int value from local variable 1
3: ireturn //return an integer from a method
int bar();
Code:
0: iconst_0
1: ireturn
public static void main(java.lang.String[]) throws java.lang.Exception;
Code:
0: new #2; //class my/pckage/Main
3: dup
4: invokespecial #3; //Method "<init>":()V
7: invokevirtual #4; //Method foo:()I
10: pop
11: new #2; //class my/pckage/Main
14: dup
15: invokespecial #3; //Method "<init>":()V
18: invokevirtual #5; //Method bar:()I
21: pop
22: return
}
Вы можете видеть, что это не оптимизируется на этом уровне.
То, решит ли JIT-компилятор оптимизировать это во время выполнения, будет зависеть от конкретной целевой платформы.