Производительность. Должен ли я избегать делегирования конструктора?
Мне было интересно, существует ли любая разница в производительности между запуском конструктора из конструктора (например, делегирование конструктора), а не.
Пожалуйста, не интерпретируйте этот вопрос, поскольку я поддерживаю избыточность, например, копирование длинных конструкторов для повышения производительности. Я понимаю, что в большинстве случаев вызов конструктора внутри конструктора желательно по многим причинам, отличным от производительности. (Читаемость, например)
В качестве примера, это класс Vector3D
, который я недавно создал:
public class Vector3D {
public final int x, y, z;
public Vector3D() {
this(0, 0, 0);
}
public Vector3D(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
}
}
Получаю ли я выгоду от не вызова this(0, 0, 0)
и просто установки переменных таким образом?
public class Vector3D {
public final int x, y, z;
public Vector3D() {
this.x = 0;
this.y = 0;
this.z = 0;
}
public Vector3D(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
}
}
Ответы
Ответ 1
Main.java
package pokus1;
public class Main {
public int m_a;
public int m_b;
public Main(int a, int b) {
m_a = a;
m_b = b;
}
public Main() {
this(0,0);
}
public static void main(String[] args) {
Main main = new Main();
}
}
Выход Javap (javap -v Main.class) для pokus1.Main():
Вы видите инструкцию invokespecial
на смещении 3
? Это вызов pokus1.Main(int a,int b)
. Так что фундаментально да, более эффективно не вызывать второй конструктор. Но есть много оптимизаций в текущих реализациях JVM, таких как метод inlining, компиляция точно в срок и т.д., Поэтому я думаю, вам не нужно об этом думать, иначе вы можете думать о каждом вызове java, если это необходимо.
public pokus1.Main();
flags: ACC_PUBLIC
Code:
stack=3, locals=1, args_size=1
0: aload_0
1: iconst_0
2: iconst_0
3: invokespecial #24 // Method "<init>":(II)V
6: return
LineNumberTable:
line 16: 0
line 17: 6
LocalVariableTable:
Start Length Slot Name Signature
0 7 0 this Lpokus1/Main;
Ответ 2
Вы никогда не выиграете от дублирования кода. Это преждевременная оптимизация. Вызов метода ничего не стоит, если вы не выполняете его очень часто за короткое время. В этом случае допустимо встроить код, если он не используется в слишком многих местах системы, но это не ваш случай.
Представьте, что в один прекрасный день вы добавите еще одну функцию в свой класс. Если вы ввели код, вам нужно будет обновить два конструктора вместо одного. Все биты кода, с которыми связана эта логика, должны быть связаны в коде (в основном, вызывая одни и те же методы/используя одни и те же классы). Это то, как вы создаете многоразовый код.
Не переусердствуйте о производительности, сначала подумайте о дизайне, ясности и повторном использовании. Части вашей системы, которые действительно должны быть эффективными, являются алгоритмическими, это не должно влиять на дизайн.
Ответ 3
Как правило, нет никакой разницы, потому что компилятор только во времени строит короткие методы.
Кроме того, даже если код не был вложен, служебные данные, вызванные двумя командами ветвления в машинных кодах, вряд ли существенно повлияют на время выполнения всей программы, если программа не тратит большую часть времени на работу с этими векторами.