2015-05-02 3 views
14

Мне было интересно, если есть любая разница в производительности между запуском конструктора из конструктора (aka. Делегирование конструктора), а не.Производительность: Должен ли я избегать делегирования конструктора?

Пожалуйста, не интерпретируйте этот вопрос, поскольку я поддерживаю избыточность, например, копирование длинных конструкторов для повышения производительности. Я понимаю, что в большинстве случаев вызов конструктора внутри конструктора желательно по многим причинам, отличным от производительности. (Читаемость, например)

В качестве примера, это 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; 
    } 
} 
+0

Даже если есть разница, вы не сможете это заметить. – isnot2bad

+1

Не влияет на производительность; у вас просто перегруженная версия ... и если да, то это было бы неуместно (для этого случая). Вы можете попробовать и сделать этот тест самостоятельно –

+0

Все методы, вызываемые из конструкторов, должны быть окончательными (согласно PMD) ... – xerx593

ответ

6

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; 
+0

Удивлен, что это не было! Это Oracle JDK? – Dici

+1

Dici: он скомпилирован с компилятором Eclipse. Но он может быть встроен во время выполнения, так что все в порядке. – Krab

+0

Я не знаю ... это можно сделать статически, так зачем делать это во время выполнения? – Dici

10

Вы никогда не выиграете от дублирующего кода. Это преждевременная оптимизация. Вызов метода ничего не стоит, если вы не выполняете его очень часто за короткое время. В этом случае допустимо встроить код, если он не используется в слишком многих местах системы, но это не ваш случай.

Представьте, что в один прекрасный день вы добавите еще одну функцию в свой класс. Если вы ввели код, вам нужно будет обновить два конструктора вместо одного. Все биты кода, с которыми связана эта логика, должны быть связаны в коде (в основном, вызывая одни и те же методы/используя одни и те же классы). Вот как вы создаете многоразовый код.

Не задумывайтесь о производительности, сначала подумайте о дизайне, ясности и повторном использовании. Части вашей системы, которые действительно должны быть эффективными, являются алгоритмическими, это не должно влиять на дизайн.

+1

Я бы понял, если у вас есть длинный конструктор и копирование будет избыточным, но для 'Vector3D'? Это настоящий класс, и реалистично нет никакого вреда в выборе трех линий над одним. В этом случае сделать это одним способом так же просто, как сделать это другим. Тогда вопрос: каким образом я это сделаю? – octopod

+3

Потому что код предназначен для людей и должен быть доступен для чтения. Вы не знаете, что происходит с вашим кодом при компиляции, но я предполагаю, что он будет компилироваться в отдельные конструкторы, но вы его пишете. Существует синтаксис для вызова других конструкторов одного класса, доверия создателей языка и его использования, они должны были подумать об этом. – Dici

+0

.. не приходит «кто-то» и перезаписывает свой конструктор «int, int, int». – xerx593

4

Как правило, нет никакой разницы, потому что the just in time compiler inlines short methods.

Кроме того, даже если код не был вставлен в очередь, накладные расходы, вызванные двумя командами ветвления в машинный код, вряд ли существенно повлияют на время выполнения всей программы, если программа не тратит большую часть времени на работу с этими векторами.

+0

Я думал, что JIT оставляет конструкторы только отдельно от inline op. Нет? –

Смежные вопросы