Идиомы языка Java
1. цикл
В важных циклах исключите вызовы методов при определении завершения цикла.
Например: будет
for(int i=0; i<collection.size();i++){ ... }
Заменить на…
for(int i=0; n=collection.size();i<n;i++){...}
Обычно элементы, не связанные с индексом цикла, перемещаются за пределы цикла.
for(int i=0; терминал=x.length;i<terminal;i++){x[i] = x[i]/scaleA *scaleB;}
Это должно быть:
Двойной масштаб = масштабB*scaleA;for(int i=0; терминал=x.length;i<терминал;i++){x[i] = x[i]/scale;}
2. нить
Устранить конкатенацию строк
При создании длинных строк всегда используйте StringBuffter вместо String.
Предварительно выделить пространство StringBuffer StringBuffer sb = new StringBuffer(5000);
3. Основные типы данных
Используйте базовые типы данных в важных циклах (данные int обычно работают быстрее, чем данные long/double).
Классы-оболочки базовых типов данных (Boolean, Integer и т. д.) в основном используются, когда передаваемый параметр метода должен быть ссылкой на объект (а не на базовый тип данных).
Используйте модификатор static Final для всех константных алгебраических выражений, чтобы на константы было легче ссылаться (компилятор предварительно вычисляет константные выражения).
4. аномальный
Исключения используются только для единственного истинного состояния ошибки, например, создание исключения и выполнение блока catch являются дорогостоящими (в основном из-за получения моментального снимка стека потока при создании исключения).
Исключение генерируется только тогда, когда условие действительно является исключительным. Чтобы создать исключение, вы сначала создаете новый объект.
Конструктор интерфейса Throwable вызывает собственный метод fillInStackTrace(). Метод fillInStackTrace() проверяет стек и собирает информацию о трассировке вызовов.
Всякий раз, когда генерируется исключение, виртуальной машине приходится корректировать стек вызовов, поскольку во время обработки создается новый объект.
Исключения следует использовать только для обработки ошибок и не следует использовать для управления ходом программы.
Оптимизируйте компилятор и среду выполнения, поместив несколько вызовов методов в блок try/catch вместо реализации нескольких блоков try/catch для каждого вызова метода.
try{ Some.method1(); //Сложно для java1.4 }catch(method1Exception e){ обрабатываем исключение
1 // для оптимизации этого кода } try{ Some.method2(); //Сложно для java1.4 }catch(method2Exception e){ обрабатываем исключение
2 // для оптимизации этого кода } try{ Some.method3(); //Сложно для java1.4 }catch(method3Exception e){ обрабатываем исключение
3 // для оптимизации этого кода
}
должно быть записано как:
try{ Some.method1(); Some.method2(); Some.method3(); //Сложно для java1.4 }catch(method1Exception e){ обработать исключение 1 }catch(method2Exception e){ обработать исключение 2 }catch( метод3Exception e) {обработать исключение 3}
5. эталон
Обратите внимание, что все эти советы будут различаться в зависимости от платформы и виртуальных машин.
Например: в некоторых контейнерах сервлетов быстрее выводить байты через OutputStream.
2. В других контейнерах быстрее будет выводить символы через PrintWriter
Эти советы описывают наиболее переносимые рекомендации.
Возможно, вам придется запустить несколько тестов, чтобы определить, что работает быстрее всего на вашей платформе.
6. Создайте экземпляр класса без использования ключевого слова new.
Когда вы создаете экземпляр класса с использованием ключевого слова new, автоматически вызываются все конструкторы в цепочке конструкторов.
Но если объект реализует интерфейс Cloneable, мы можем вызвать его метод clone(). Метод clone() не вызывает никаких конструкторов классов.
Если при использовании шаблона проектирования вы используете режим Factory для создания объекта, очень просто использовать метод clone() для создания нового экземпляра объекта.
Например, ниже приведена типичная реализация шаблона Factory:
общественный статический кредит getNewCredit () {вернуть новый кредит () };
После оптимизации:
частный статический кредит BaseCredit = новый общественный статический кредит getNewCredit () { return (Credit) BaseCredit.clone ();}
Вышеупомянутые идеи также полезны для обработки массивов.
7. Используйте неблокирующий ввод-вывод
JDK с более ранними версиями Java не поддерживают неблокирующие API ввода-вывода. Чтобы избежать блокировки ввода-вывода, некоторые приложения создают большое количество потоков (в лучших случаях используется пул буферов). Этот метод можно увидеть во многих приложениях, которые должны поддерживать параллельные потоки ввода-вывода, таких как веб-серверы, приложения для котировок и аукционов и т. д. Однако создание потоков Java требует значительных накладных расходов.
В JDK 1.4 появилась неблокирующая библиотека ввода-вывода (java.nio). Если вашему приложению требуется более старая версия JDK, существует пакет, поддерживающий неблокирующий ввод-вывод.
8. Не инициализируйте переменные повторно
По умолчанию при вызове конструктора класса Java инициализирует переменные определенными значениями: всем объектам присваивается значение null, целочисленным переменным (byte, short, int, long) присваивается значение 0, а переменным float и double присваивается значение 0.0, логическое значение устанавливается равным false.
Это следует особенно отметить, когда класс является производным от другого класса, поскольку при создании объекта с использованием ключевого слова new все конструкторы в цепочке конструкторов будут вызываться автоматически.
9. Попробуйте указать последний модификатор класса
Классы с модификатором Final не являются производными. В базовом API Java существует множество примеров применения метода Final, например java.lang.String. Указание Final для класса String не позволяет людям переопределить метод length().
Кроме того, если класс обозначен как окончательный, все методы класса будут окончательными. Компилятор Java будет искать возможности встроить все конечные методы (это зависит от конкретной реализации компилятора). Это может повысить производительность в среднем на 50%.
10. Используйте локальные переменные, когда это возможно.
Параметры, передаваемые при вызове метода, и временные переменные, созданные во время вызова, сохраняются в стеке (Stack), что происходит быстрее. Другие переменные, такие как статические переменные, переменные экземпляра и т. д., создаются в куче и работают медленнее. Кроме того, в зависимости от конкретного компилятора/JVM локальные переменные могут быть дополнительно оптимизированы. См. «Использовать переменные стека везде, где это возможно».
11. Умножение и деление
Рассмотрим следующий код:
для (значение = 0; значение <100000; значение +=5) { alterX = значение * 8; myResult = значение * 2;
После оптимизации:
for (val = 0; val < 100000; val += 5) { alterX = val << 3; myResult = val << 1;
Модифицированный код больше не выполняет операцию умножения на 8, а вместо этого использует эквивалентную операцию сдвига на 3 бита влево. Каждый сдвиг влево на 1 бит эквивалентен умножению на 2. Соответственно, операция сдвига вправо на 1 бит эквивалентна делению на 2. Стоит отметить, что хотя операция сдвига выполняется быстро, она может затруднить понимание кода, поэтому лучше добавить несколько комментариев.
частный статический Credit BaseCredit = новый публичный статический Credit getNewCredit() {return (Credit) BaseCredit.clone();}