Skip to content

Latest commit

 

History

History
229 lines (184 loc) · 30.7 KB

File metadata and controls

229 lines (184 loc) · 30.7 KB

Оглавление

Java Core

Какие бывают операции в стримах? Напишите стрим?

Есть 2 вида операций в Java Stream:

  • Промежуточные (Intermediate) - filter, map, sorted, peek и т.д. Возвращают Stream.
  • Терминальные (Terminal) - collect, forEach, count, reduce, findFirst, anyMatch и т.д. Возвращают результат стрима и запускают его выполнение.

Кроме того, будет полезно ознакомиться с содержимым пакета java.util.stream и доступными коллекторами из Collectors.

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

Почитать подробнее про стримы лучше в Java Doc, но можно и в статьях:

Посмотреть:

к содержанию

Что поменялось с Java 8 по Java <CURRENT_VERSION>?

Java имеет богатую историю. На данный момент проекты чаще всего разделяются на:

  • legacy-проекты с версией Java меньше 8
  • проекты на Java 8, самая распрастранённая и популярная
  • проекты на Java 9+ (точнее либо 11 LTS, либо последние полугодовые релизы)

Между 8 и 9 версиями случился небольшой разлом с частичной потерей обратной совместимости, а потом приколы лицензирования подъехали, поэтому миграция и в без того консервативном мире Java-приложений идёт медленно. Однако идёт, и если вы собеседуетесь в компанию, где этот переход уже осуществили, то, вероятно, у вас поинтересуются, что же там с Java 8 поменялось, чем живёт и дышит современная Java.

На момент выхода статьи, имеем:

Найти ссылки на документацию к API, языку и виртуальной машине, release notes и сравнить API между версиями можно в Java-альманахе.

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

  • Amber - проект по реализации маленьких, но продуктивных улучшений языка Java. В рамках данного проекта постепенно реализуется и независимо выходит целый набор JEP: var (JDK 10), Switch Expressions, Sealed Types, Records, Text Blocks, Pattern Matching для instanceof и другие.
  • Panama - проект по улучшению взаимодействия между JVM и нативным кодом. На Хабре есть статья с разъяснениями и интервью с Владимиром Ивановым на эту тему.
  • Loom - проект по внедрению в Java легковесных потоков. На Хабре есть две прекрасные статьи с разъяснениями: раз и два.
  • Valhalla - это проект по созданию нескольких больших и сложных улучшений языка и VM. В него входят: Inline types, Generics over Primitive Types, Enhanced volatiles и другие возможные или необходимые в рамках проекта улучшения.
  • Lanai - проект по улучшению рендеринга настольных Java-приложений на MacOS путём использования Metal Apple platform API. C 14 мая 2020 появились Early-Access сборки.
  • и другие

Отдельно нужно упомянуть GraalVM - это JDK и виртуальная машина Java, которая создана, чтобы объединить необъединяемое:

  • быстрое выполнение Java
  • уменьшение времени старта и потребления памяти для Java
  • комбинирование и исполнение программ, написанных на различных ЯП, в том числе на платформо-зависимых
  • общие инструменты для всех ЯП
  • поддержка JIT и AOT-компиляции
  • и т.п.

Послушать на тему:

  • Два выпуска подкаста Javaswag: раз и два
  • Выпуск 172 Java подкаста Подлодка, в гости к которому пришёл Тагир Валеев

Почитать на Хабре:

И не только:

Посмотреть:

к содержанию

В какой кодировке строки в Java? Как хранятся строки внутри класса String? Как устроен String?

До Java 9 все строки имели кодировку UTF-16 (2 байта на символ) и хранились в массиве char.

С Java 9 пришло такое изменение как Compact String. Если все символы строки входят в множество символов Latin-1 (а это подавляющее большинство строк), то каждый из них может поместиться в 1 байт, поэтому в этом случае массив char избыточен. В результате было принято решение заменить массив char на массив byte, что позволяет строкам Latin-1 расходовать меньше памяти. Кодировка строки хранится в отдельном поле byte coder, значение которого представляет Latin-1 или UTF-16.

Также интересной особенностью является кеширование классом String своего hashcode.

Строки являются неизменяемыми, наследоваться от строк запрещено (final class). Все операции по изменении строки возвращают её новый экземпляр, в том числе и конкатенация строк. Компилятор умеет оптимизировать конкатенацию и превращать её в объект StringBuilder и совокупность вызовов методов append. ОДНАКО! В Java 9 вошёл JEP 280: Indify String Concatenation, который изменил эту оптимизацию и пошёл ещё дальше. Теперь вместо StringBuilder генерируется bytecode для вызова StringConcatFactory через invokedynamic, поэтому стоит расслабиться и чаще выбирать +.

Ещё можно упомянуть про String pool - это выделяемое в heap пространство, которое используется для оптимизации потребления памяти при хранении строк. Благодаря ему одинаковые строковые литералы могут ссылаться на один и тот же объект.

Стоит помнить, что с помощью String.intern() производительности особой не добиться, а можно наоборот пустить всё по миру. Лучше напишите свою реализацию. Подоробнее читайте в статье Алексея Шипилёва - JVM Anatomy Quark #10: String.intern().

Кроме того, equals и методы поиска (например indexOf) оптимизируются JIT компилятором на нативном уровне.

Посмотреть доклады Алексея Шипилёва на тему строк: Катехизис java.lang.String и The Lord of the Strings: Two Scours.

Подробнее:

к содержанию

Сколько в байт занимает каждый из примитивных типов в памяти? А объект?

Казалось бы:

  • byte - 1 байт
  • short - 2 байта
  • int - 4 байта
  • long - 8 байт
  • char - 2 байта
  • float - 4 байта
  • double - 8 байт

А размер boolean не упоминается в спецификации вовсе. Однако также спецификация не запрещает использовать для хранения примитива больше памяти - главное, чтобы размер был достаточным для всех значений. Конкретный объём таки зависит от реализации JVM. Не последнюю роль в этом играет выравнивание данных в памяти.

Похожая ситуация и со ссылочными типами - спецификация JVM не требует какой-то определённой структуры для объектов и отдаёт её на откуп реализации. Все тонкости и секреты занимаемой объектами памяти раскрывает Алексей Шипилёв в своей статье Java Objects Inside Out.

Подробнее:

Если вас заинтересовало представление объектов в jvm и их реализация (и вы умеете-могёте читать C++), то можно пойти посмотреть исходники openjdk. Начать, например, отсюда:

к содержанию

Какие ссылки бывают в Java?

Типы ссылок в Java:

  • Strong reference - обычная переменная ссылочного типа в Java. Объект такой ссылки очищается GC не раньше, чем станет неиспользуемым (никто нигде на него больше не ссылается).
  • Слабые ссылки - сборщик мусора тем или иным образом не учитывает связь ссылки и объекта в куче при выявлении объектов, подлежащих удалению. Объект будет удалён даже при наличии слабой ссылки на него:
  • Soft reference - мягкая ссылка, экземпляр класса SoftReference. Объект гарантированно будет собран GC до возникновения OutOfMemoryError. Может использоваться для реализации кэшей, увеличивающихся без риска OutOfMemoryError для приложения.
  • Weak reference - слабая ссылка, экземпляр класса WeakReference. Не препятствует утилизации объекта и игнорируется GC при сборке мусора. Может использоваться для хранения некоторой связанной с объектом информации до момента его смерти. Также стоит обратить внимание на WeakHashMap.
  • Phantom reference - фантомная ссылка, экземпляр класса PhantomReference. Не препятствует утилизации объекта и игнорируется GC при сборке мусора и имеет ряд особенностей, описанных ниже. Может быть применена для получения уведомления, что объект стал неиспользуемым и можно освободить связанные с ним ресурсы (как более надёжный вариант, чем finalize(), вызов которого не гарантируется, может проводить сеансы воскрешения и вообще deprecated).

Чтобы достать объект из слабых ссылок, необходимо вызывать метод get(). Если объект недостижим, то метод вернёт null. Для фантомных ссылок всегда возвращается null.

При создании слабой ссылки в конструктор можно, а для PhantomReference необходимо, передать экземпляр ReferenceQueue - в очереди будет сообщение, когда ссылка протухнет. Для SoftReference и WeakReference это будет ДО финализации объекта, а для PhantomReference ПОСЛЕ. Однако фактическое удаление объекта фантомной ссылки из памяти не производится до момента её очистки.

Подробнее:

к содержанию