Предисловие
Я пересмотрел его в марте 2016 года и вернулся, почему мне нужно оптимизировать код на основе моей собственной работы и моего ежедневного обучения. Прежде чем мне поручиться, мое заявление было таким:
Точно так же, как кита, ест креветки, может быть, есть одна или две креветки, не очень эффективно для китов, но если вы едите слишком много креветок, киты, естественно, будут заполнены. Оптимизация кода такая же. Возможно, одна или две оптимизации имеют небольшую значимость для повышения эффективности работы кода, но если вы можете обратить внимание на оптимизацию кода повсюду, это, как правило, очень полезно для повышения эффективности работы кода.
Эта точка зрения, в настоящем представлении, является причиной оптимизации кода, но это не совсем правильно. Сегодня, с разработкой механической технологии, серверы часто имеют 8 ядер, 16 ядер и 64-битные процессоры, а эффективность выполнения кода очень высока. StringBuilder заменяет StringBuffer и ArrayList заменяет Vector, что повышает эффективность работы кода Minuscule. Даже если вы заметите каждую точку в проекте, вы не можете увидеть каких -либо очевидных изменений в операции кода.
Я думаю, что наиболее важной ролью оптимизации кода должна быть: избегать неизвестных ошибок. Во время кода, работающего в Интернете, часто возникают многие неожиданные ошибки, потому что онлайн -среда и среда разработки очень разные, а позиционирование ошибок часто является очень маленькой причиной. Однако, чтобы решить эту ошибку, нам нужно сначала самооценка, а затем выпустить файл класса, который будет заменен, приостановил бизнес и перезапустите. Для зрелого проекта последний на самом деле оказывает очень большое влияние, что означает, что пользователи не могут получить доступ к приложению в течение этого периода. Следовательно, при написании кода, обращение внимания на различные детали из источника, взвешивание и использование лучших вариантов значительно избегают неизвестных ошибок и значительно уменьшат рабочую нагрузку в долгосрочной перспективе.
Цели оптимизации кода:
1. Уменьшите объем кода
2. Повышение эффективности работы кода
Некоторые из содержимого этой статьи поступают из Интернета, а некоторые поступают из ежедневной работы и изучения. Конечно, это не важно. Важно то, действительно ли подробности этой оптимизации кода полезны. Затем эта статья будет обновляться в течение долгого времени. Пока вы сталкиваетесь с подробностями оптимизации кода, которые стоит поделиться, эта статья будет время от времени обновляться.
Детали оптимизации кода
(1) Попробуйте как можно больше указать окончательный модификатор класса и метода
Занятия с окончательными модификаторами не подлежат производству. В Java Core API есть много примеров применения финала, таких как java.lang.string, и весь класс является окончательным. Указание окончательного модификатора для класса может предотвратить унаследование класса, и указание окончательного модификатора для метода может предотвратить переопределение метода. Если класс указан как окончательный, все методы этого класса являются окончательными. Компилятор Java будет искать возможности для внедрения всех окончательных методов. Встроенный имеет большое значение для повышения эффективности работы Java. Для получения подробной информации см. Оптимизация времени выполнения Java. Этот шаг может повысить производительность в среднем на 50%.
(2) Попробуйте повторно использовать объекты
Специально для использования строковых объектов, вместо этого следует использовать StringBuilder/StringBuffer, когда происходит конкатенация строки. Поскольку виртуальные машины Java не только должны тратить время на создание объектов, им также может потребоваться потратить время на сбор и обработку мусора в будущем, генерируя слишком много объектов окажет большое влияние на производительность программы.
(3) Используйте локальные переменные как можно больше
Параметры, прошедшие при вызове метода, и временные переменные, созданные в вызове, хранятся в стеке, что быстрее. Другие переменные, такие как статические переменные, переменные экземпляра и т. Д., Все созданы в куче, которая медленнее. Кроме того, поскольку переменные, созданные в стеке, закончено, это содержимое исчезло, и дополнительная сборы мусора не требуется.
(4) Закройте поток во времени
Во время программирования Java будьте осторожны при выполнении подключения к базе данных и потоковой передачи ввода -вывода. После использования закройте его вовремя, чтобы выпустить ресурсы. Поскольку работа этих больших объектов вызовет накладные расходы на большие системы, и если вы не будете осторожны, это приведет к серьезным последствиям.
(5) минимизировать повторные расчеты переменных
Чтобы прояснить концепцию, даже если в методе есть только одно предложение, оно все еще используется, включая создание кадров стека, защита сайта при вызове метода и восстановления сайта при вызове метода. Так, например, следующая операция:
for (int i = 0; i <list.size (); i ++) {...}Рекомендуется заменить его:
for (int i = 0, length = list.size (); i <length; i ++) {...}Таким образом, когда List.Size () очень большой, он уменьшает много потребления
(6) Попробуйте принять ленивую стратегию загрузки, то есть создать ее при необходимости
Например:
String str = "aaa"; if (i == 1) {list.add (str);}Рекомендуется заменить его:
if (i == 1) {string str = "aaa"; list.add (str);}(7) Используйте аномалии с осторожностью
Аномалия не подходит для производительности. Чтобы сделать исключение, вы должны сначала создать новый объект. Конструктор брошенного интерфейса вызывает локальный метод синхронизации с именем filinstacktrace (). Метод FillinStackTrace () проверяет стек и собирает информацию о трассировке вызовов. Пока исключение брошено, виртуальная машина Java должна настроить стек вызовов, потому что при обработке создается новый объект. Исключения могут использоваться только для обработки ошибок и не должны использоваться для управления потоком программ.
(8) Не используйте попробуйте ... поймать ... в цикле, его следует помещать на самый внешний слой
Согласно мнениям, выдвинутым пользователями пользователей сети, я думаю, что это стоит обсудить
(9) Если можно оценить длину добавления контента, укажите начальную длину для классов сбора и инструментов, реализованных в массиве на базовом уровне.
Например, ArrayList, LinkedLlist, StringBuilder, StringBuffer, Hashmap, Hashset и т. Д. Примите stringBuilder в качестве примера:
StringBuilder () // По умолчанию выделить 16 символов Space StringBuilder (int size) // По умолчанию выделить 16 символов Space StringBuilder (String Str) // По умолчанию Allock 16 символов + str.length () пространство символов
Его способность инициализации может быть установлена через конструктор класса (здесь мы ссылаемся не только на приведенный выше StringBuilder), что может значительно повысить производительность. Например, StringBuilder, длина представляет количество символов, которые может сохранить текущий StringBuilder. Поскольку, когда StringBuilder достигнет своей максимальной емкости, он увеличит свою собственную емкость до 2 раза и добавит 2. Когда StringBuilder достигнет своей максимальной емкости, ему придется создать новый массив символов и скопировать содержимое старого массива символов в новую массив символов - это очень операция, обслуживающая производительность. Представьте себе, что если вы можете оценить, что 5000 символов хранятся в массиве символов без указания длины, мощность 2 ближайших к 5000 составляет 4096, а 2, добавленные к каждому расширению, независимо от 2, тогда::
На основании 4096, подайте заявку на массивы символов размером 8194, которые сразу же составляют до 12290 массивов. Если вы можете указать массивы символов размером 5000 в начале, вы сохраните более чем в два раза больше места, чтобы скопировать исходные символы 4096 в новую массив символов.
Это не только тратит пространство памяти, но и снижает эффективность работы кода. Следовательно, не ошибочно устанавливать разумную инициализацию для сбора и классов инструментов, реализованных в базовом массиве, что принесет немедленные результаты. Тем не менее, обратите внимание, что коллекции, такие как HashMap, которые реализованы в массивах + связанных списках, не должны устанавливать начальный размер, так же, как ваш оценочный размер, потому что возможность только одного объекта, подключенного к таблице, почти 0. Рекомендуется установить начальный размер на n мощности 2. Если вы можете оценить, что есть 2000 элементов, установить его на новый Hashmap (128) и New Hashmap (256).
(10) При копировании большого количества данных используйте команду System.ArrayCopy ()
(11) Умножение и деление используют операции смены
Например:
for (val = 0; val <100000; val += 5) {a = val * 8; b = val / 2;}Использование операций смены может значительно повысить производительность, потому что в нижней части компьютера операция позиционирования является наиболее удобной и быстрой, поэтому рекомендуется его изменить:
for (val = 0; val <100000; val += 5) {a = val << 3; b = val >> 1;}Хотя операция смены быстро, она может затруднить понимание кода, поэтому лучше добавить соответствующие комментарии.
(12) Не постоянно создавайте ссылки на объекты в цикле
Например:
for (int i = 1; i <= count; i ++) {Object obj = new Object (); }Этот подход приведет к тому, что ссылка объекта графа существует в памяти. Если счет большой, он будет потреблять память. Рекомендуется изменить его на:
Объект obj = null; for (int i = 0; i <= count; i ++) {obj = new Object ();}Таким образом, в памяти есть только одна ссылка на объект объекта. Каждый раз, когда используется New Object (), ссылка объекта объекта указывает на другой объект, но в памяти есть только один объект, который значительно сохраняет пространство памяти.
(13) На основании рассмотрения эффективности и проверки типов, массив следует использовать как можно больше. ArrayList должен использоваться только в том случае, если размер массива не может быть определен.
(14) Попробуйте использовать HashMap, ArrayList и StringBuilder. Если это не необходимо для безопасности потока, не рекомендуется использовать хештибл, вектор и Stringbuffer. Последние три имеют накладные расходы из -за использования механизмов синхронизации.
(15) Не объявляйте массивы общественным статичным финалом
Поскольку это бессмысленно, это только определяет ссылку как статический финал, а содержание массива все еще может быть изменено по желанию. Объявление массива публикой является уязвимостью безопасности, что означает, что массив может быть изменен внешними классами
(16) Попробуйте использовать отдельные чехлы в подходящих случаях
Использование синглтонов может уменьшить нагрузку, сократить время нагрузки и повысить эффективность нагрузки, но не все места подходят для синглтонов. Проще говоря, синглтоны в основном применимы к следующим трем аспектам:
Управляйте использованием ресурсов, контролируйте генерацию одновременных экземпляров контроля доступа ресурсов посредством синхронизации потоков, чтобы достичь цели сохранения ресурсов для контроля обмена данными и обеспечения связи между несколькими не связанными процессами или потоками без установления прямых ассоциаций.
(17) Старайтесь не использовать статические переменные по желанию
Вы должны знать, что когда на объект ссылается переменная, определенная как статическая, GC обычно не перерабатывает память кучи, занятую объектом, например:
открытый класс A {Private Static B B = new B (); }В настоящее время жизненный цикл статической переменной B такой же, как и у класса A. Если класс A не удален, объект B, указанный по ссылке B
(18) Очистите больше необходимых сессий во времени
Чтобы очистить сеансы, которые больше не активны, многие серверы приложений имеют тайм -аут сеанса по умолчанию, обычно 30 минут. Когда сервер приложений должен сохранить больше сеансов, если не хватает памяти, операционная система передаст часть данных на диск. Сервер приложений может также сбросить некоторые неактивные сеансы на диск в соответствии с алгоритмом MRU (чаще всего используется недавно) и может даже бросить недостаточные исключения для памяти. Если сеанс должен быть сброшен на диск, он должен быть сериализован в первую очередь. В крупномасштабных кластерах сериализация объектов стоит дорого. Следовательно, когда сеанс больше не требуется, метод httpsession Invalidate () должен быть вызван во времени, чтобы очистить сеанс.
(19) Коллекция, которая реализует интерфейс Randomaccess, такой как ArrayList, должен использовать наиболее распространенное для цикла вместо Foreach Loop для прохождения
Это рекомендуется JDK пользователям. Объяснение JDK API интерфейса случайного интерфейса: реализация интерфейса RandomAccess используется, чтобы указать, что он поддерживает быстрый случайный доступ. Основная цель этого интерфейса состоит в том, чтобы позволить общим алгоритмам изменять свое поведение, чтобы он мог обеспечить хорошую производительность при применении к случайным или непрерывным спискам доступа. Практический опыт показывает, что если экземпляры класса, которые реализуют интерфейс случайного, доступны случайным образом, эффективность использования обычных для петли будет выше, чем у использования петлей Foreach; И наоборот, если он доступен последовательно, будет более эффективно использовать итератор. Вы можете использовать коды, аналогичные следующим, для вынесения суждений:
if (list ancessionof randomaccess) {for (int i = 0; i <list.size (); i ++) {}} else {iterator <?> iterator = list.iterable (); while (iterator.hasnext ()) {iterator.next ()}}Основным принципом реализации петля Foreach является итератор, см. Java Syntax Sugar 1: Параметры переменной длины и принцип цикла Foreach. Таким образом, вторая половина предложения «наоборот, если оно будет последовательно, использование итератора будет более эффективным» означает, что экземпляры класса, которые доступны последовательно, пересекаются с использованием цикла Foreach.
(20) Используйте блоки синхронного кода вместо метода синхронизации
Это уже четко указано в блоке метода синхронизированного блокировки статьи в многопоточном модуле. Если нельзя определить, что весь метод должен быть синхронизирован, постарайтесь использовать синхронизированные кодовые блоки, чтобы избежать синхронизации тех кодов, которые не должны синхронизировать, что влияет на эффективность выполнения кода.
(21) объявить константу статическим финалом и назовите его в капитале
Таким образом, это содержимое может быть помещено в постоянный пул во время компиляции, избегая расчета генерируемых постоянных значений во время выполнения. Кроме того, название имени константы в капитале также может способствовать различию между констант и переменными
(22) Не создавайте некоторые неиспользованные объекты, не импортируйте некоторые неиспользованные классы
Это не имеет смысла. Если «значение локальной переменной I не используется» и «Import Java.Util никогда не используется» в коде, пожалуйста, удалите это бесполезное содержимое
(23) Избегайте использования отражения во время работы программы
Для получения дополнительной информации см. Reflection. Отражение - это очень мощная функция, предоставленная Java пользователям. Мощные функции часто означают низкую эффективность. Не рекомендуется часто использовать механизм отражения во время работы программы, особенно метод вызова метода. Если это действительно необходимо, наводящий на мысль о создании объекта посредством размышлений и вставка в память, когда проект запускается. Пользователь заботится только о самой быстрой скорости отклика при взаимодействии со сверстником, и ему все равно, сколько времени требуется для начала проекта сверстников.
(24) Используйте пул соединений базы данных и пул потоков
Оба пула используются для повторного использования объектов, первое избегает частого открытия и закрытия соединений, а последний избегает частого создания и разрушения нитей
(25) Используйте буферизованные входные и выходные потоки для операций ввода -вывода
Буферированные входные и выходные потоки, а именно буфериальная читатель, буферист, буферизаторноптуст, BufferedOutputStream, который может значительно повысить эффективность ввода -вывода
(26) Используйте ArrayList для сцен с более последовательной вставкой и случайным доступом и используйте LinkedList для сцен с большей делецией элементов и промежуточной вставкой.
Это известно, понимая принципы ArrayList и LinkedList
(27) Не позволяйте слишком много формальных параметров в публичном методе
Общественный метод - это метод, предоставляемый внешнему миру. Если вы дадите эти методы слишком много формальных параметров, есть два основных недостатка:
Нарушение объектно-ориентированной идеи программирования. Java подчеркивает, что все является объектом. Слишком много формальных параметров и не соответствует объектно-ориентированной идее программирования. Слишком много параметров неизбежно приведет к увеличению вероятности ошибок в вызовах методов.
Что касается того, на сколько «слишком много» относится, 3 или 4. В студенческую таблицу есть 10 полей информации студентов. Эти 10 параметров могут быть инкапсулированы в класс сущности в качестве формальных параметров метода вставки.
(28) Когда строковые переменные и константы строкости равны, записаны перед строковыми константами
Это относительно распространенный трюк, если есть следующий код:
String str = "123"; if (str.equals ("123")) {...}Рекомендуется изменить его на:
String str = "123"; if ("123" .equals (str)) {...}Это может в основном избежать исключений нулевого указателя
(29) Пожалуйста, знайте, что на Java нет разницы между if (i == 1) и if (1 == i), но с точки зрения привычек чтения рекомендуется использовать первое
Иногда люди спрашивают, есть ли какая -то разница между «if (i == 1)» и «if (1 == i)»? Это начинается с C/C ++.
В C/C ++ условие суждения «if (i == 1)» действительнее, и оно основано на 0 и не 0. 0 означает ложь, а не 0 означает истину. Если есть такая часть кода:
int i = 2; if (i == 1) {...} else {...}C/C ++ Судьи, что «i == 1» не является действительным, поэтому он представлен 0, то есть False. Но если:
int i = 2; if (i = 1) {...} else {...}Если программист случайно пишет «если (i == 1)» как «if (i = 1)», то возникнет проблема. Назначьте I на 1 в IF IF. Если вы определите, что содержание в нем не 0, возвращаемое True, но я, очевидно, 2, а сравниваемое значение - 1, ложно, которое следует возвращать. Эта ситуация, скорее всего, произойдет при разработке C/C ++ и вызовет некоторые трудные ошибки. Следовательно, чтобы избежать неправильных операций по назначению разработчиков в операторах IF, рекомендуется написать оператор IF AS:
int i = 2; if (1 == i) {...} else {...}Таким образом, даже если разработчик случайно записывает «1 = I», компилятор C/C ++ может проверить его как можно скорее, потому что мы можем назначить переменную значение I– 1, но мы не можем присвоить постоянное значение 1 на i.
Однако в Java синтаксис «if (i = 1)» C/c ++ невозможно появиться, потому что после написания этого синтаксиса Java составляет и сообщает о ошибке «несоответствие типа: не может преобразовать из int в логическое». Однако, хотя нет семантической разницы между «if (i == 1)» и «if (1 == i)» на Java, было бы лучше рекомендовать использовать первое с точки зрения привычек чтения.
(30) Не используйте метод ToString () на массиве
Давайте посмотрим на то, что напечатано с помощью ToString () для массивов:
int i = 2; if (1 == i) {...} else {...}оказаться:
I@18A992F
Первоначальное намерение состоит в том, чтобы распечатать содержимое массива, но оно может вызвать исключение из нулевого указателя, поскольку ссылка на массив является нулевой. Однако, хотя это не имеет смысла для массива ToString (), содержимое в коллекции может быть распечатано для коллекции ToString (), потому что родительский класс коллекции, метод объекта ToString () переписан.
(31) не делайте преобразования силы вниз по основным типам данных, которые не имеют диапазона
Это никогда не получит желаемый результат:
public static void main (string [] args) {long l = 12345678901234l; int i = (int) l; System.out.println (i);}Мы можем ожидать получить некоторые из них, но результат в том, что:
1942892530
Объясните это. Долго на Java составляет 8 байтов с 64 битами, поэтому представление 12345678901234 на компьютере должно быть:
0000 0000 0000 0000 0000 1011 0011 1010 0111 0011 1100 1110 0010 1111 1111 0010
Данные типа Int составляют 4 байта и 32 бита. Первые 32 бита приведенной выше строки бинарных данных взяты из низкого бита:
0111 0011 1100 1110 0010 1111 1111 0010
Эта цепочка двоичного файла представлена как десятичная децимальная 1942892530, так что это контент -выход на консоли выше. Из этого примера мы можем сделать два вывода:
1. Тип данных по умолчанию типа целочисленного типа IT, Long L = 12345678901234L. Это число превысило диапазон int, поэтому в конце есть L, указывая на то, что это длинное число. Кстати, тип типа плавающей запятой по умолчанию двойной, поэтому при определении плавания его следует записать как «float f = 3,5f»
2. Далее напишите другое предложение «int ii = l + i;» и сообщит об ошибке, потому что Long + int является длинным и не может быть назначено Int
(32) Данные, не используемые в классе публичных сборов, должны быть удалены вовремя
Если класс сбора является общедоступным (то есть он не является свойством в методе), то элементы в этой коллекции не будут автоматически выпущены, потому что всегда есть ссылки, указывающие на них. Следовательно, если определенные данные в публичной коллекции не используются, и они не будут удалены, это приведет к тому, что публичная коллекция будет продолжать расти, что приведет к тому, что система может иметь потенциал для утечки памяти.
(33) Преобразовать основной тип данных в строку. Базовый тип данных.toString () является самым быстрым способом, за которым следуют string.valueof (data), а Data +"" является самым медленным
Обычно существует три способа преобразования основного типа данных. У меня есть данные типа целочисленного типа, то есть toString (), string.valueof (i) и i+"" три способа. Насколько эффективны три способа? Смотрите тест:
public static void main (string [] args) {int looptime = 50000; Целое число I = 0; long starttime = System.currentTimeMillis (); for (int j = 0; j <looptime; j ++) {string str = string.valueof (i); } System.out.println ("string.valueof ():" + (system.currenttimemillis () - starttime) + "ms"); startTime = System.CurrentTimeMillis (); for (int j = 0; j <looptime; j ++) {string str = i.ToString (); } System.out.println ("integer.tostring ():" + (system.currenttimemillis () - starttime) + "ms"); startTime = System.CurrentTimeMillis (); for (int j = 0; j <looptime; j ++) {string str = i+""; } System.out.println ("i + /" /":" + (System.currentTimeMillis () - startTime) + "ms");}Результат работы:
String.valueof (): 11msInteger.toString (): 5 мс + "": 25 мс
Поэтому, когда вы преобразуете основной тип данных в строку в будущем, вы должны уделять приоритет использования метода ToString (). Что касается почему, это очень просто:
Метод String.valueOf() называется методом Integer.toString() , но он будет коротким, чтобы оценить метод Integer.toString() перед вызовом. Я позвоню в I + "". В нижнем слое используется реализация StringBuilder. Сначала используйте метод добавления, чтобы сплачивать его, а затем использовать метод ToString (), чтобы получить строку.
По сравнению с тремя, это, очевидно, самый быстрый, самый быстрый, самый медленный
(34) Используйте наиболее эффективный способ пересечения карты
Есть много способов пройти карту. Обычно, что нам нужно, чтобы пересечь ключ и значение на карте. Рекомендуемый и наиболее эффективный метод:
public static void main (string [] args) {hashmap <string, string> hm = new hashmap <string, string> (); hm.put ("111", "222"); SET <Map.Entry <String, String >> intrySet = hm.entrySet (); Итератор <map.Entry <string, string >> iter = intrySet.iterator (); while (iter.hasnext ()) {map.entry <string, string> entry = iter.next (); System.out.println (entry.getKey () + "/t" + entry.getValue ()); }} Если вы просто хотите использовать значение по значению ключа этой карты, было бы более уместно использовать « Set<String> keySet = hm.keySet();"
(35) Рекомендуется работать отдельно для близкого () ресурсов
Это означает, например, у меня есть такая часть кода, как это:
try {xxx.close (); Yyy.close ();} catch (Exception e) {...}Рекомендуется изменить его на:
try {xxx.close ();} catch (Exception e) {...} try {yyy.close ();} catch (Exception e) {...}Хотя это немного хлопотно, он может избежать утечки ресурсов. Мы думаем, что если нет модифицированного кода, если xxx.close () вызовет исключение, он введет блок улова. Yyy.close () не будет выполнен, а ресурс Yyy не будет переработан и будет занят все время. С большим количеством подобных кодов, это может привести к просой ручке ресурсов. После перехода на следующий метод написания гарантируется, что XXX и YYY будут закрыты, несмотря ни на что.
(36) Для Threadlocal вы должны удалить до или после использования
В настоящее время во всех проектах используются технология объединения потоков, что очень хорошо. Вы можете динамически настроить количество потоков и повторного использования.
Однако, если вы используете Threadlocal в своем проекте, не забудьте удалить его до или после использования. Это связано с тем, что технология пула потоков, упомянутая выше, предназначена для повторного использования потока, что означает, что во время запуска кода поток не будет уничтожен и будет ждать следующего использования. Давайте посмотрим на ссылку в классе потока, которая удерживает Threadlocal.Threadlocalmap:
/* Значения Threadlocal, относящиеся к этому потоку. Эта карта поддерживается * с помощью класса Threadlocal. */Threadlocal.Threadlocalmap Threadlocals = null;
Поток не уничтожен, означает, что данные в Threadlocal.Threadlocalmap предыдущего набора потока все еще существуют. Когда следующий поток повторно использует этот поток, вполне вероятно, что то, что вы получаете, является данными предыдущего набора потока, а не желаемого контента.
Эта проблема очень неясна. Как только возникают ошибки этой причиной, очень трудно найти эту проблему без соответствующего опыта или прочной основы. Поэтому вы должны обратить на это внимание при написании кода, что уменьшит вашу последующую рабочую нагрузку.
(37) Не забудьте заменить номер дьявола постоянным определением. Существование номера дьявола значительно уменьшит читабельность кода. Независимо от того, используют ли строковые константы постоянные определения, могут зависеть от ситуации.
(38) Когда первоначальное назначение длинного или длинного, используйте верхнюю часть L, вместо нижнего регистра L, потому что букву L очень легко путать с номером 1, эта точка очень подробно и стоит отметить
(39) Все методы переписывания должны сохранить аннотацию @Override
Есть три причины для этого:
(1) Понятно, что этот метод унаследован от родительского класса
(2) методы getObject () и get0bject (). Четвертое письмо первого - «O», а четвертый родитель и ребенок последнего - «0». Добавление аннотации @Override может немедленно определить, успешно ли переписать.
(3) Измените подпись метода в абстрактном классе, и класс реализации немедленно сообщит об ошибке компиляции.
(40) Рекомендуется использовать вновь введенный класс инструментов объектов в JDK7 для сравнения объектов, равных, непосредственно A.Equals (b), и существует риск исключений нулевого указателя.
(41) Не используйте "+" для строк сплайсинга в корпусе петли, но используйте StringBuilder для постоянного добавления
Позвольте мне поговорить о причине, по которой я не использую "+" для сплайсинга строки. Если у меня есть метод:
public String AppendStr (String oristr, String ... AppendStrs) {if (appendStrs == null || appendStrs.length == 0) {return oristr; } for (String appendStr: appendStrs) {oristr += appendStr; } вернуть oristr;}После составления этого кода декомпиляция файла .class с помощью javap -c для перехвата ключевой части:
Это означает, что каждый раз, когда виртуальная машина встречается с оператором «+», чтобы сплачивать строку, она будет новым строителем StringBuilder, затем вызовет метод добавления и, наконец, вызовет метод ToString (), чтобы преобразовать строку в объект Oristr. То есть, сколько раз петля будет новой StringBuilder (), который является пустой тратой памяти.
(42) Не захватывайте класс исключений времени выполнения, определенный в библиотеке классов Java, унаследованной от Runtimeexception
Эффективность обработки исключений низкая, большая часть классов исключений в среде выполнения может быть полностью избежать программистами, такими как:
(43) Избегайте использования случайных экземпляров по нескольким потокам. Хотя совместное использование экземпляра безопасно, это приведет к снижению производительности из-за конкуренции за то же семя. После JDK7 вы можете использовать Threadlocalrandom для получения случайных чисел
Объясните причину, по которой конкуренция за то же семя вызывает ухудшение производительности. Например, взгляните на реализацию метода nextint () случайного класса:
public int nextint () {return next (32); }Следующий метод (int bits) называется, который является защищенным методом:
Защищенный int next (int bits) {long oldseed, nextseed; Семя Atomiclong = this.eed; do {oldseed = seed.get (); NextSeed = (OldSeed * Multiplier + добавление) & Mask; } while (! Seed.compareAndset (Oldseed, NextSeed)); return (int) (nextseed >>> (48 - биты));}И семя здесь является глобальной переменной:
/*** Внутреннее состояние, связанное с этим генератором псевдордомов. * (Спецификации для методов в этом классе описывают текущие * вычисления этого значения.) */ Частное окончательное семя атомалонга;
Когда несколько потоков получают случайные числа одновременно, они будут конкурировать за одно и то же семя, что приведет к снижению эффективности.
(44) Статические классы, классы синглтона и заводские классы устанавливают свои конструкторы на частные
Это потому, что нам не нужно новичок на улице. После установки конструктора для частного, мы гарантируем, что эти классы не будут производить объекты экземпляра.
PostScript
Отличный код исходит от каждой маленькой оптимизации. Обращение внимания на каждую деталь может не только повысить эффективность работы программы, но и избежать многих неизвестных проблем.
Выше приведены 44 предложения по оптимизации кода Java, представленные редактором. Я надеюсь, что это будет полезно для вас. Если у вас есть какие -либо вопросы, пожалуйста, оставьте мне сообщение, и редактор ответит вам вовремя. Большое спасибо за вашу поддержку сайту wulin.com!