Ява, насколько дорого это вызов метода



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



public class BinarySearchTree<E extends Comparable<E>>{
private BinaryTree<E> root;
private final BinaryTree<E> EMPTY = new BinaryTree<E>();
private int count;
private Comparator<E> ordering;

public BinarySearchTree(Comparator<E> order){
ordering = order;
clear();
}

public void clear(){
root = EMPTY;
count = 0;
}
}


было бы более оптимальным для меня просто скопировать и вставить две строки в мой метод clear() в конструктор вместо вызова фактического метода? Если да, то насколько это важно? Что делать, если мой конструктор сделал 10 вызовов методов с каждым просто установка переменной экземпляра в значение? Какая лучшая практика программирования?

536   12  

12 ответов:

было бы более оптимальным для меня просто скопировать и вставить две строки в мой метод clear() в конструктор вместо вызова фактического метода?

компилятор может выполнить оптимизацию. И так может JVM. Терминология, используемая автором компилятора и авторами JVM, является "встроенным расширением".

если да, то какая разница?

измерить его. Часто вы обнаружите, что это не имеет никакого значения. И если вы считаете, что это горячая точка производительности, вы ищете не в том месте; вот почему вам нужно будет ее измерить.

Что делать, если мой конструктор составила 10 вызовов методов с каждым просто установив переменную значение?

опять же, это зависит от сгенерированного байт-кода и выполнения каких-либо оптимизаций, выполняемых виртуальной машиной Java. Если компилятор/JVM может встроить вызовы метода, он выполнит оптимизацию, чтобы избежать накладные расходы на создание новых кадров стека во время выполнения.

какова лучшая практика программирования?

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

что-то об оптимизации абсолютно верно.

нет никакой причины С точки зрения производительности чтобы встроить метод. Если это проблема производительности, JIT в вашем JVM будет встроен в него. В java вызовы методов настолько близки к бесплатным, что об этом не стоит думать.

как говорится, здесь есть другая проблема. А именно, это и плохая практика программирования для вызова переопределяемого метода (т. е. не final,static или private) из конструктора. (Эффективная Java, 2-е изд., стр. 89 в пункте под названием "оформление и документ для наследования или же запретить его")

что произойдет, если кто-то добавляет подкласс BinarySearchTree под названием LoggingBinarySearchTree что переопределяет все открытые методы с кодом, как:

public void clear(){
  this.callLog.addCall("clear");
  super.clear();
}

тут LoggingBinarySearchTree никогда не будет технологичная! Проблема в том, что this.callLog будет null когда BinarySearchTree конструктор работает, но clear это называется переопределенным, и вы получите NullPointerException.

обратите внимание, что Java и C++ отличаются здесь: в C++, конструктор суперкласса, который вызывает virtual метод в конечном итоге вызывает тот, который определен в суперклассе, а не переопределенный. Люди, переключающиеся между двумя языками, иногда забывают об этом.

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

Я бы определенно оставил все как есть. Что делать, если вы измените clear() логика? Было бы непрактично найти все места, где вы скопировали 2 строки кода.

рекомендуется семь раз отмерь и один раз отрежь.

после того, как вы потратили время оптимизации, вы никогда не сможете получить его обратно! (Поэтому сначала измерьте его и спросите себя, стоит ли его оптимизировать. Сколько фактического времени вы сэкономите?)

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

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

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

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

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

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

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

  • было бы полезно иметь этот метод доступен за пределами этого класса?
  • было бы полезно иметь этот метод в других методах?
  • было бы неприятно переписывать это каждый раз, когда мне это нужно?
  • может ли универсальность метода быть увеличена с использованием нескольких параметры?

Если любое из вышеперечисленного верно, оно должно быть завернуто в свой собственный метод.

сохранить clear() метод, когда это помогает читабельности. Иметь недостижимый код дороже.

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

"преждевременная оптимизация является корнем все зло.- Дональд Кнут

Я бы не стал беспокоиться о вызове метода, а о логике метода. Если бы это были критические системы, и система должна была "быть быстрой", я бы посмотрел на оптимизацию кодов, которая занимает много времени для выполнения.

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

Как уже говорили другие, стоимость вызова метода тривиальна для nada, так как компилятор оптимизирует его для вас.

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

другой вопрос--ваш метод clear () устанавливает корень пустым, который инициализируется при создании объекта. Если затем добавить узлы в пустые, а затем вызвать clear (), вы не будете сбрасывать корневой узел. Это то поведение, которое вы хотите?

Comments

    Ничего не найдено.