Процедурная JAVA Flashcards
Какие примитивные типы данных есть в Java?
- byte 8 бит -2^7 .. -2^7 - 1;
- short 16 бита -2^15 .. -2^15 -1;
- int 32 бита -2^31 .. -2^31 -1;
- long 64 битов -2^63 .. -2^63 -1;
- double 64 битов ;
- float 32 битов ;
- char 16 бит ;
- boolean 4 бита (1 бит в массивах);
Что такое char?
Это примитивный тип данных, который хранит в себе номер символа в формате юникода и занимает 2 байта, поэтому диапазон хранимых значений от 0 до 65535
16-разрядное беззнаковое целое, представляющее собой символ UTF-16 (буквы, цифры и символы).
Сколько памяти занимает boolean?
Зависит от реализации JVM
1 байт в массивах, 4 байта вне его
Что такое классы-обертки?
Классы обертки типа Byte Short Integer Long Double Float Character Boolean, они являются ссылочными типами данных в отличии от их аналогов-примитивов, и хранят внутри себя значение примитива.
Они менее производительны но имеют методы типа toString, также например можно получить минимальное и максимальное значение.
Объекты классов-оберток являются неизменяемыми (Immutable)).
Используются для реализации дженериков.
Что такое автоупаковка ?
Автоупаковка - присвоение классу обертки значения примитивного типа, без явного использования конструктора класса.
Autoboxing происходит:
- При присвоении значения примитивного типа переменной соответствующего класса-обёртки.
- При передаче примитивного типа в параметр метода, ожидающего соответствующий ему класс-обёртку.
Важно отметить, что целочисленные классы оберток созданных с помощью авто упаковки кэшируются JVM и обертки с одинаковыми значениями будут иметь ссылку на один объект.
Что такое автораспаковка?
Автораспаковка - преобразование класса-обёртки в соответствующий ему примитивный тип. Если при распаковке класс-обёртка был равен null, произойдет исключение java.lang.NullPointerException.
Unboxing происходит:
- При присвоении экземпляра класса-обёртки переменной соответствующего примитивного типа.
- При передаче объекта класса-обёртки в метод, ожидающий соответствующий примитивный тип.
- В выражениях, в которых один или оба аргумента являются экземплярами классов-обёрток.
Так как арифметические операторы и операторы сравнения (исключение == и !=) применяются только к примитивным типам.
Что такое явное и неявное приведение типов?
Привидение типов - это перевод одного типа данных в другой путем его расширения или сужения.
Явное приведение - явное сужение от большего к меньшему. Необходимо явно указать сужаемый тип.
Неявное приведение – автоматическое расширение типа переменной от меньшего к большему.
В случае с объектами мы можем делать неявное(автоматическое) приведение от наследника к родителю, но не наоборот, иначе получим ClassCastException.
В каких случаях в java нужно
использовать явное приведение?
Явное приведение типов может привести к потере данных, если целевой тип недостаточно велик для хранения значения исходного типа.
Кроме того, приведение объекта к несовместимому типу может привести к возникновению ClassCastException во время выполнения. Следовательно, необходимо использовать явное приведение типов с осторожностью и только тогда, когда вы уверены, что преобразование безопасно и не приведет к непреднамеренному поведению.
Что такое пул интов?
Для более эффективного использования памяти, в джаве используются так называемые пулы.
Есть строковый пул, Integer pool итд. Когда мы создаем объект не используя операцию new, объект помещается в пул, и в последствии, если мы захотим создать такой же объект (опять не используя new), новый объект создан не будет, а мы просто получим ссылку на наш объект из пула.
В классе-обертке Integer есть внутренний класс IntegerCache – пул (pool) целых чисел в промежутке [-128; 127], так как это самый часто встречающийся диапазон.
Он объявлен как private static. В этом внутреннем классе кешированные объекты находятся в массиве cache[].
Кеширование выполняется при первом использовании класса-обертки.
После первого использования вместо создания нового экземпляра (кроме использования конструктора), используются кешированные объекты, JVM берет их из пула.
Какие нюансы у строк в Java?
- Это неизменяемый (immutable) и финализированный тип данных;
- Все объекты класса String JVM хранит в пуле строк;
- Объект класса String можно получить используя двойные кавычки;
- Можно использовать оператор + для конкатенации строк;
- Начиная с Java 7 строки можно использовать в конструкции switch.
- Каждый объект можно привести к строке используя метод
.toString
Что такое пул строк?
Пул строк – это набор строк хранящийся в Heap.
- Пул строк помогает экономить память, но по этой же причине создание строки занимает больше времени;
- Когда для создания строки используются “, то сначала ищется строка в пуле с таким же значением, если находится, то просто возвращается ссылка, иначе создается новая строка в пуле, а затем возвращается ссылка на неё;
- При использовании оператора new создаётся новый объект String. Затем при помощи метода intern() эту строку можно поместить в пул или же получить из пула ссылку на другой объект String с таким же значением;
- Пул строк является примером паттерна «Приспособленец» (Flyweight).
Пул строк и Integer хранится в heap, но ссылки на объекты хранятся в stack.
Почему не рекомендуется изменять строки в цикле? Что рекомендуется использовать?
Т.к. строка неизменяемый класс, то возрастает потребление ресурсов при редактировании, т.к. каждую итерацию при редактировании будет создаваться новый обьект строки.
Рекомендуется использовать StringBuilder или StringBuffer.
Почему строки не рекомендуется использовать для хранения паролей?
- Пул строк
Так как строки в Java хранятся в пуле строк, то ваш пароль в виде обычного текста будет доступен в памяти, пока сборщик мусора не очистит её. И поскольку String используются в String pool для повторного использования, существует довольно высокая вероятность того, что пароль останется в памяти надолго, что совсем не безопасно. - Рекомендации авторов
Java сама по себе рекомендует использовать метод getPassword () из класса JPasswordField, который возвращает char []. - Случайная печать в логах
С типом String всегда существует опасность того, что текст, хранящийся в строке будет напечатан в файле логов или в консоли. В то же время в случае использования Array, вы не будете печатать содержимое массива, а только его расположение в памяти.
Почему String неизменяемый и финализированный класс?
- Для возможности реализации строкового пула (String pool)
Виртуальная машина имеет возможность сохранить много места в памяти (heap space) т.к. разные строковые переменные указывают на одну переменную в пуле. При изменяемости строк было бы невозможно реализовать интернирование, поскольку если какая-либо переменная изменит значение, это отразится также и на остальных переменных, ссылающихся на эту строку. - Безопасность
Изменяемость строк несло бы в себе потенциальную угрозу безопасности приложения. Поскольку в Java строки используются для передачи параметров для авторизации, открытия файлов и т.д. — неизменяемость позволяет избежать проблем с доступом. - Для многопоточности. Неизменяемые строки потокобезопасны
Так как строка неизменяемая то, она безопасна для много поточности и один экземпляр строки может быть совместно использован различными потоками. Это позволяет избежать синхронизации для потокобезопасности. Таким образом, строки в Java полностью потокобезопасны. - Строки используются classloader, и неизменность обеспечивает правильность
загрузки класса. - Ключ для HashMap
Поскольку строка неизменная, её hashcode кэшируется в момент создания и нет никакой необходимости рассчитывать его снова. Это делает строку отличным кандидатом для ключа в Map и его обработка будет быстрее, чем других ключей HashMap. Поэтому строка наиболее часто используется в качестве ключа HashMap.
- можно передавать строку между потоками не опасаясь, что она будет изменена
- отсутствуют проблемы с синхронизацией потоков
- отсутствие проблем с утечкой памяти
- отсутствие проблем с доступом и безопасностью при использовании строк для передачи параметров авторизации, открытия файлов и т.д.
- кэширование hashcode
- Экономия памяти при использовании пула строк для хранения повторяющихся строк.
Почему строка является популярным ключом в HashMap в Java?
Поскольку строки неизменяемы, и их хэш код вычисляется и кэшируется в момент создания,а также не требует повторного пересчета при дальнейшем использовании.
Поэтому в качестве ключа HashMap они будут обрабатываться быстрее.
Что делает метод intern() в классе String?
Для того чтобы поместить строку созданную через new в пул строк, или присвоить переменной ссылку на значение строки из пула, если такое значение там уже существует.
Можно ли использовать строки в конструкции switch?
Да, начиная с Java 7 в операторе switch можно использовать строки, ранние версии Java не поддерживают этого. При этом:
- участвующие строки чувствительны к регистру;
- используется метод equals() для сравнения полученного значения со значениями case, поэтому во избежание NullPointerException стоит предусмотреть проверку на null.
- согласно документации Java 7 для строк в switch, компилятор Java формирует более эффективный байткод для строк в конструкции switch, чем для сцепленных условий if-else.
Какая основная разница между String, StringBuffer, StringBuilder?
Класс String является неизменяемым (immutable) - модифицировать объект такого класса нельзя, можно лишь заменить его созданием нового экземпляра.
Класс StringBuffer изменяемый - использовать StringBuffer следует тогда, когда необходимо часто модифицировать содержимое, потокобезопасный
Класс StringBuilder был добавлен в Java 5 и он во всем идентичен классу StringBuffer за исключением того, что он не синхронизирован и поэтому его методы выполняются значительно быстрей, потоконебезопасный
Что такое StringJoiner?
Класс StringJoiner используется, чтобы создать последовательность строк, разделенных
разделителем с возможностью присоединить к полученной строке префикс и суффикс:
```
public static void main(String[] args) {
StringJoiner joiner = new StringJoiner(“, “);
joiner.add(“John”);
joiner.add(“Jane”);
joiner.add(“Jim”);
String result = joiner.toString(); System.out.println(result); // John, Jane, Jim ~~~
Существуют ли в java многомерные массивы?
Многомерные массивы в их классическом понимании в java не существуют.
Многомерный массив всегда прямоугольный и неразрывен в памяти.
А то, что в java считается многомерным - в других языках ещё называют “зубчатым массивом” или массивом массивов.
Какими значениями инициируются переменные по умолчанию?
byte 0
short 0
int 0
long 0L
float 0.0f
double 0.0d
char ‘\u0000’
boolean false
**Объекты (в том числе String) ** — null
Локальные (в методе) переменные не имеют значений по умолчанию, их имеют поля класса.
Не static-поле класса будет инициализировано после того, как будет создан объект этого класса.
А static-поле будет инициализировано тогда, когда класс будет загружен виртуальной Java машиной.
Что такое сигнатура метода?
Сигнатура метода - название метода и его параметры.
В сигнатуру метода не входит возвращаемое значение, а также бросаемые им исключения.
А сигнатура метода в сочетании с типом возвращаемого значения и бросаемыми исключениями называется контрактом метода.
Расскажите про метод main
Метод main() — Является, точкой входа в программу и вызывается JVM.
С его первой строки будет начато выполнение программы.
Как только заканчивается выполнение метода main(), так сразу же завершается работа самой программы.
static - чтобы JVM смогла загрузить его во время компиляции.
public static void и сигнатура - обязательное декларирование.
Может быть перегружен.
В приложении может быть несколько таких методов.
Если метод отсутствует, то компиляция возможна, но при запуске будет получена ошибка Error: Main method not found
.
public static void main(String[] args) {}
Каким образом переменные передаются в методы, по значению или по ссылке?
В Java параметры всегда передаются только по значению, что определяется как «скопировать значение и передать копию».
С примитивами это будет копия содержимого.
Со ссылками - тоже копия содержимого, т.е. копия ссылки.
При этом внутренние члены ссылочных типов через такую копию изменить возможно, а вот саму ссылку, указывающую на экземпляр - нет.
Что такое тернарный оператор выбора?
Тернарный условный оператор ?: - оператор, которым можно заменить некоторые конструкции операторов if-then-else.
Выражение записывается в следующей форме:
условие ? выражение1 : выражение2
Если условие выполняется, то вычисляется выражение1 и его результат становится результатом выполнения всего оператора. Если же условие равно false, то вычисляется выражение2 и его значение становится результатом работы оператора. Оба операнда выражение1 и выражение2 должны возвращать значение одинакового (или совместимого) типа.
Расскажите про приведение типов. Что такое понижение и повышение типа?
- Тождественное (identity). Преобразование выражения любого типа к точно такому же типу всегда допустимо и происходит автоматически.
- Расширение (повышение, upcasting) примитивного типа (widening primitive). Означает, что осуществляется переход от менее емкого типа к более ёмкому. Например, от типа byte (длина 1 байт) к типу int (длина 4 байта). Такие преобразование безопасны в том смысле, что новый тип всегда гарантировано вмещает в себя все данные, которые хранились в старом типе и таким образом не происходит потери данных. Этот тип приведения всегда допустим и происходит автоматически.
- Сужение (понижение, downcasting) примитивного типа (narrowing primitive). Означает, что переход осуществляется от более емкого типа к менее емкому. При таком преобразовании есть риск потерять данные. Например, если число типа int было больше 127, то при приведении его к byte значения битов старше восьмого будут потеряны. В Java такое преобразование должно совершаться явным образом, при этом все старшие биты, не умещающиеся в новом типе, просто отбрасываются - никакого округления или других действий для получения более корректного результата не производится.
- Расширение объектного типа (widening reference). Означает неявное восходящее приведение типов или переход от более конкретного типа к менее конкретному, т.е. переход от потомка к предку. Разрешено всегда и происходит автоматически.
- Сужение объектного типа (narrowing reference). Означает нисходящее приведение, то есть приведение от предка к потомку (подтипу). Возможно только если исходная переменная является подтипом приводимого типа. При несоответствии типов в момент выполнения выбрасывается исключение ClassCastException. Требует явного указания типа.
- Преобразование к строке (to String). Любой тип может быть приведен к строке, т.е. к экземпляру класса String.
- Запрещенные преобразования (forbidden). Не все приведения между произвольными типами допустимы. Например, к запрещенным преобразованиям относятся приведения от любого ссылочного типа к примитивному и наоборот (кроме преобразования к строке).
Для проверки возможности приведения нужно воспользоваться оператором instanceof:
Parent parent = new Child(); if (parent instanceof Child) { Child child = (Child) parent;
Если передать массив и изменить его в методе, то будет ли изменяться текущий массив?
Да, текущий массив изменится тоже.