Как стать автором
Обновить
629
0
Тагир Валеев @tagir_valeev

Программист

Отправить сообщение

Изменения в стандартной библиотеке Java 10

Время на прочтение10 мин
Количество просмотров21K

Недавно состоялся релиз-кандидат Java 10, и на Хабре вышла статья, где перечислены JEP'ы, вошедшие в новый релиз. Однако не все изменения в Java получают свой JEP. В частности, небольшие дополнения стандартной библиотеки практически всегда происходят без JEP'ов. При этом частенько практической пользы от них даже больше, чем от более серьёзных изменений, которые удостоились JEP'а. Давайте посмотрим, что добавилось в стандартную библиотеку Java 10.

Читать дальше →
Всего голосов 38: ↑38 и ↓0+38
Комментарии11

Статический анализ и property-based тестирование: вместе мы сила

Время на прочтение7 мин
Количество просмотров6.5K

Как известно, баги есть во всех программах. Есть множество способов борьбы с ними: юнит-тесты, ревью, статический анализ, динамический анализ, дымовое тестирование и так далее. Иногда для искоренения определённого бага полезно сочетать разные методики.


Я разрабатываю Java-инспекции в IntelliJ IDEA, которая большей частью написана на Java. В некотором смысле я нахожусь в привилегированном положении по сравнению с другими программистами: доработать статический анализатор IDE, чтобы находить новый класс ошибок — это моя прямая рабочая обязанность, которая при этом же позволяет найти и обезвредить баги в этой же самой IDE. Хочу поделиться одной такой историей успеха.

Читать дальше →
Всего голосов 23: ↑22 и ↓1+21
Комментарии6

Пылесосим код IDEA Ultimate с помощью анализа потоков данных

Время на прочтение5 мин
Количество просмотров9K
IntelliJ IDEA содержит тысячи инспекций для Java-кода. Большинство из них работает как продвинутые регулярные выражения: по определённому шаблону они ищут фрагменты программы, которые выглядят как опечатки, избыточны, некрасивы или могут работать медленно. Но есть инспекция совсем другого рода. У неё несколько странное название: «Constant conditions & exceptions». В действительности она выполняет анализ потоков данных в Java-методах с помощью так называемого «символьного выполнения». В результате такого анализа могут обнаружиться некоторые подозрительные факты. Вот некоторые примеры таких фактов:

  • Разыменование ссылки может привести к NullPointerException
  • Условие всегда истинно или ложно
  • Индекс массива всегда за пределами допустимых границ
  • Приведение типа может привести к ClassCastException
Читать дальше →
Всего голосов 41: ↑41 и ↓0+41
Комментарии15

Используйте Stream API проще (или не используйте вообще)

Время на прочтение7 мин
Количество просмотров181K

С появлением Java 8 Stream API позволило программистам писать существенно короче то, что раньше занимало много строк кода. Однако оказалось, что многие даже с использованием Stream API пишут длиннее, чем надо. Причём это не только делает код длиннее и усложняет его понимание, но иногда приводит к существенному провалу производительности. Не всегда понятно, почему люди так пишут. Возможно, они прочитали только небольшой кусок документации, а про другие возможности не слышали. Или вообще документацию не читали, просто видели где-то пример и решили сделать похоже. Иногда это напоминает анекдот про «задача сведена к предыдущей».


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

Читать дальше →
Всего голосов 71: ↑71 и ↓0+71
Комментарии50

Что там с JEP-303 или изобретаем invokedynamic

Время на прочтение8 мин
Количество просмотров10K

Блогеры и авторы, пытающиеся быть на передовой, уже немало писали про проект Amber в Java 10. В этих статьях обязательно упоминается вывод типов локальных переменных, улучшения enum и лямбд, иногда пишут про pattern matching и data-классы. Но при этом незаслуженно обходится стороной JEP 303: Intrinsics for the LDC and INVOKEDYNAMIC Instructions. Возможно, потому что мало кто понимает, к чему это вообще. Хотя любопытно, что именно об этой фиче ребята из NIX_Solutions фантазировали на Хабре год назад.


Широко известно, что в виртуальной машине Java, начиная с версии 7, есть интересная инструкция invokedynamic (она же indy). Про неё многие слышали, однако мало кто знает, что она делает на самом деле. Кто-то знает, что она используется при компиляции лямбда-выражений и ссылок на методы в Java 8. Некоторые слышали, что через неё реализована конкатенация строк в Java 9. Но хотя это полезные применения indy, изначальная цель всё же немного другая: делать динамический вызов, при котором вы можете вызывать разный код в одном и том же месте. Эта возможность не используется ни в лямбдах, ни в конкатенации строк: там поведение всегда генерируется при первом вызове и остаётся постоянным до конца работы программы (всегда используется ConstantCallSite). Давайте посмотрим, что можно сделать ещё.

Читать дальше →
Всего голосов 31: ↑31 и ↓0+31
Комментарии15

Статический анализ → уязвимость → профит

Время на прочтение5 мин
Количество просмотров10K

В статьях про PVS-Studio всё чаще говорят об уязвимостях и дефектах безопасности, которые можно найти с помощью статического анализа. Авторов этих статей критикуют (и я в том числе), что не каждая ошибка является дефектом безопасности. Возникает однако интересный вопрос, можно ли пройти весь путь от сообщения статического анализатора до эксплуатации найденной проблемы и получения какой-то выгоды. В моём случае выгода всё же осталась теоретической, но эксплуатировать ошибку удалось, не особо вникая в код проекта.

Читать дальше →
Всего голосов 43: ↑42 и ↓1+41
Комментарии11

Начинается разработка OpenJDK 10

Время на прочтение1 мин
Количество просмотров10K

Сегодня Mark Reinhold объявил об открытии репозиториев mercurial для Java 10, и разработчики, имевшие статус committer и выше в проекте Java 9, получили возможность размещать багфиксы и мелкие улучшения, которые не предполагается вносить в Java 9. Всем разработчикам (например, мне) обновили статус на страничке переписи OpenJDK.


Крупные изменения вносить пока не рекомендуется во избежание конфликтов. Изменения в Java 9 ещё не завершены и некоторое время придётся их переносить в Java 10. При отсутствии конфликтов процедура будет автоматизирована, так что тем, кто продолжает вносить исправления в Java 9, скорее всего не придётся лишний раз беспокоиться.

Читать дальше →
Всего голосов 28: ↑27 и ↓1+26
Комментарии77

Вызов методов через reflection

Время на прочтение8 мин
Количество просмотров65K

Все программисты на Java явно или неявно пользуются reflection для вызова методов. Даже если вы не делали этого сами, это за вас наверняка делают библиотеки или фреймворки, которые вы используете. Давайте посмотрим, как этот вызов устроен внутри и насколько это быстро. Будем глядеть в OpenJDK 8 с последними обновлениями.

Читать дальше →
Всего голосов 34: ↑34 и ↓0+34
Комментарии14

Лямбды и анонимные классы: кто больше жрёт

Время на прочтение7 мин
Количество просмотров49K

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

Читать дальше →
Всего голосов 74: ↑69 и ↓5+64
Комментарии35

Супермедленный и супербыстрый бенчмарк

Время на прочтение5 мин
Количество просмотров23K

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


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

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

Читать дальше →
Всего голосов 65: ↑60 и ↓5+55
Комментарии48

JIT-компилятор оптимизирует не круто, а очень круто

Время на прочтение6 мин
Количество просмотров54K

Недавно Лукас Эдер заинтересовался в своём блоге, способен ли JIT-компилятор Java оптимизировать такой код, чтобы убрать ненужный обход списка из одного элемента:


// ... а тут мы "знаем", что список содержит только одно значение
for (Object object : Collections.singletonList("abc")) {
    doSomethingWith(object);
}

Вот мой ответ: JIT может даже больше. Мы будем говорить про HotSpot JVM 64 bit восьмой версии. Давайте рассмотрим вот такой простой метод, который считает суммарную длину строк из переданного списка:


static int testIterator(List<String> list) {
    int sum = 0;
    for (String s : list) {
        sum += s.length();
    }
    return sum;
}
Читать дальше →
Всего голосов 63: ↑62 и ↓1+61
Комментарии129

Статический анализатор HuntBugs: проверяем IntelliJ IDEA

Время на прочтение9 мин
Количество просмотров17K

Как многие помнят, некоторое время я развивал статический анализатор Java-байткода FindBugs. Однако проблем в FindBugs накопилось столько, что я решил, что будет проще написать новый анализатор байткода. Я не очень творчески назвал его HuntBugs. Разработка ведётся на GitHub. Он пока в ранней стадии разработки, иногда глючит и покрывает примерно 35% диагностик из FindBugs, но при этом добавляет свои интересные штуки. Попробовать можно на вашем Maven-проекте с помощью команды mvn one.util:huntbugs-maven-plugin:huntbugs (отчёт пишется в target/huntbugs/report.html). Альтернативно можно собрать вручную из гита и запустить приложение командной строки one.util.huntbugs.HuntBugs, которому можно подавать на вход JAR-файлы или каталоги с .class-файлами.


Как-нибудь потом, когда проект несколько повзрослеет, я расскажу о нём более подробно. А в этой статье я покажу, чего интересного нашёл HuntBugs в IntelliJ IDEA Community Edition. Я скачал с официального сайта и поставил последнюю версию этой IDE, а затем натравил HuntBugs на файл lib/idea.jar, в котором почти всё и лежит. Я люблю тестировать статический анализ на IDEA, потому что это IDE, в которой самой есть очень неплохой статический анализатор и разработчики им явно пользуются. Интересно посмотреть, что остаётся после него.

Читать дальше →
Всего голосов 43: ↑41 и ↓2+39
Комментарии46

Как вы можете сделать Java лучше

Время на прочтение7 мин
Количество просмотров24K

Многие люди жалуются, что в Java чего-то не хватает, что-то глючит или медленно работает. Хорошая новость: у вас есть возможность не жаловаться, а своими силами сделать Java лучше. Java практически полностью открыта в виде проекта OpenJDK. У этого проекта есть свои особенности, но в целом вам ничего не мешает самим сообщать о проблемах, исправлять их и даже разрабатывать новую функциональность. В этой статье я немного расскажу, как это делать новичку.

Читать дальше →
Всего голосов 42: ↑39 и ↓3+36
Комментарии19

Var и val в Java?

Время на прочтение4 мин
Количество просмотров43K
От переводчика: автор этой заметки — Stephen Colebourne, автор библиотеки Joda Time и Java Time API.


Следует ли добавить вывод типов локальных переменных в Java? Как раз сейчас команда разработчиков языка Java задалась этим вопросом.

Вывод типов локальных переменных


JEP-286 предлагает добавить вывод типов локальных переменных, используя новое псевдоключевое слово (интерпретируемое как «зарезервированное наименование типа»):

Явное указание типа локальных переменных зачастую не является необходимым. Разрешив разработчикам опускать его, мы хотим упростить разработку на Java, уменьшив необходимое количество формальностей, но при этом не жертвуя статической типизацией.
Читать дальше →
Всего голосов 30: ↑22 и ↓8+14
Комментарии85

Stream API: универсальная промежуточная операция

Время на прочтение12 мин
Количество просмотров28K
Я разрабатываю бесплатную библиотеку StreamEx, которая расширяет стандартное Java 8 Stream API, добавляя туда новые операции, коллекторы и источники стримов. Обычно я не добавляю всё подряд, а всесторонне рассматриваю каждую потенциальную фичу. Например, при добавлении новой промежуточной (intermediate) операции встают такие вопросы:

  1. Будет ли она действительно промежуточной, то есть не будет трогать источник до выполнения терминальной операции?
  2. Будет ли она ленивой и вытаскивать из источника не больше данных, чем требуется?
  3. Сработает ли она на бесконечном стриме? Требует ли она ограниченный объём памяти?
  4. Будет ли она хорошо параллелиться?

Минусик по любому из этих пунктов заставляет серьёзно задуматься, добавлять ли такую операцию. Минусик по первому — это сразу нет. Например, у конкурентов в jOOλ есть операция shuffle(), которая выглядит как промежуточная, но на самом деле прямо сразу потребляет весь стрим в список, перемешивает его и создаёт новый стрим. Я такое не уважаю.

Минусики по остальными пунктам не означают сразу нет, потому что есть и стандартные операции, которые их нарушают. Второй пункт нарушает flatMap(), третий — sorted(), четвёртый — всякие limit() и takeWhile() (в JDK-9). Но всё-таки я стараюсь этого избегать. Однако на днях я открыл для себя операцию, которая плохо параллелится и в зависимости от использования может не сработать на бесконечном стриме, но всё же слишком хороша. Через неё удаётся буквально в несколько строчек выразить как практически любую существующую промежуточную операцию, так и кучу несуществующих. Я назвал операцию headTail().
Читать дальше →
Всего голосов 22: ↑22 и ↓0+22
Комментарии28

Коллекции в Java: о чём многие забывают

Время на прочтение6 мин
Количество просмотров142K
Из опыта code-review и ответов на StackOverflow набралось немало моментов, касающихся Java Collections API, которые мне казались очевидными, но другие разработчики о них почему-то не знали или знали, но не чувствовали уверенности их применять. В этой статье я собираю в общую кучу всё, что накопилось.

Содержание:


  1. List.subList
  2. PriorityQueue
  3. EnumSet и EnumMap
  4. Set.add(E) и Set.remove(E) возвращают булево значение
  5. Map.put(K, V), Map.remove(K), List.set(idx, E), List.remove(idx) возвращают предыдущий элемент
  6. Map.keySet() и Map.values()
  7. Arrays.asList может быть ключом
  8. Collections.max
  9. LinkedList, Stack, Vector, Hashtable
Читать дальше →
Всего голосов 58: ↑57 и ↓1+56
Комментарии37

Пишем свой Spliterator

Время на прочтение11 мин
Количество просмотров52K
Многие из вас уже попробовали на вкус Stream API — потоки Java 8. Наверняка у некоторых возникло желание не только пользоваться готовыми потоками от коллекций, массивов, случайных чисел, но и создать какой-то принципиально новый поток. Для этого вам потребуется написать свой сплитератор. Spliterator — это начинка потока, публичная часть его внутренней логики. В этой статье я расскажу, как и зачем я писал сплитератор.
Читать дальше →
Всего голосов 23: ↑22 и ↓1+21
Комментарии34

Вычисление факториала или мощь Stream API

Время на прочтение4 мин
Количество просмотров33K
На днях появилась статья 5nw Два способа быстрого вычисления факториала, в которой приводится идея ускорения подсчёта факториала с помощью группировки перемножаемых чисел в дерево по принципу «разделяй и властвуй». Взглянув на это, я сразу понял, что тут параллельные потоки Java проявят себя во всей красе: ведь они делят задачу на подзадачи с помощью сплитераторов именно таким образом. Получается, что быстрая реализация будет ещё и красивой:

public static BigInteger streamedParallel(int n) {
    if(n < 2) return BigInteger.valueOf(1);
    return IntStream.rangeClosed(2, n).parallel().mapToObj(BigInteger::valueOf).reduce(BigInteger::multiply).get();
}

Читать дальше →
Всего голосов 24: ↑22 и ↓2+20
Комментарии44

Прокачиваем Stream API, или нужно больше сахара

Время на прочтение6 мин
Количество просмотров30K
Не так давно удалось перевести на Java 8 один из проектов, над которым я работаю. Вначале, конечно, была эйфория от компактности и выразительности конструкций при использовании Stream API, но со временем захотелось писать ещё короче, гибче и выразительнее. Поначалу я добавлял статические методы в утилитные классы, однако это делало код только хуже. В конце концов я пришёл к мысли, что надо расширять сами интерфейсы потоков, в результате чего родилась маленькая библиотека StreamEx.
Читать дальше →
Всего голосов 17: ↑16 и ↓1+15
Комментарии8

10 вещей, которых вы не знали о Java

Время на прочтение8 мин
Количество просмотров105K
Итак, вы работаете на Java с самого её появления? Вы помните те дни, когда она называлась «Oak», когда про ООП говорили на каждом углу, когда сиплюсплюсники думали, что у Java нет шансов, а апплеты считались крутой штукой?

Держу пари, что вы не знали как минимум половину из того, что я собираюсь вам рассказать. Давайте откроем для себя несколько удивительных фактов о внутренних особенностях Java.
Читать дальше →
Всего голосов 93: ↑91 и ↓2+89
Комментарии55

Информация

В рейтинге
Не участвует
Откуда
Новосибирск, Новосибирская обл., Россия
Зарегистрирован
Активность