Подготовка к java вопросам. Module 2 - примитивные типы. Какие примитивные типы есть в Java
Скачать 398.07 Kb.
|
Какие примитивные типы есть в Java byte, short, int, long, float, double, char, boolean Размерность примитивных типов byte - 1 байт, 8 бит short - 2 байта 16 бит int - 4 байта, 32 бит long - 8 байта 64 бит float - 4 байта 32 бит double - 8 байта 64 бит char - 2 байта 16 бит boolean - одиночный тип рассматривается как 4 байта в массиве 1 байт Что такое явные и неявные приведения, с чем связано их наличие? Приведение типов - это способ преобразования значений с одного типа данных к другому типу данных 2 способа приведения типов явный и неявный Явное приведение - это когда 2 типа данных несовместимы друг с другом это преобразование обычно происходит когда нужно преобразовать от типа с большей разрядностью к типу с меньшей разрядностью. Неявное приведение - это тип преобразование происходит автоматически,без указания типа данных которому он должен преобразоваться Это преобразование происходит когда присваиваем значение меньшего типа данных к большему типу данных Какие данные мы рискуем потерять при явных привидениях? Если число вне диапазона приведенному типу данных произойдет усечение данных Например: В данном случае число вне диапазона для типа byte поэтому произойдет усечение значения. Значения типа byte занимают в памяти только 8 бит. Поэтому двоичное представление числа int усекается до 8 правых разрядов, то есть 00000010, что в десятичной системе дает число 2 При преобразовании значений с плавающей точкой к целочисленным значениям, происходит усечение дробной части. При сложении char short какой результирующий тип получим? Получим тип short, так как символьный тип мы можем представить в виде числа. Разница между String, StringBuilder и StringBuffer? Объекты String являются неизменяемыми, поэтому все операции, которые изменяют строки, фактически приводят к созданию новой строки, что сказывается на производительности приложения. Для решения этой проблемы, чтобы работа со строками проходила с меньшими издержками в Java были добавлены классы StringBuffer и StringBuilder. По сути они напоминает расширяемую строку, которую можно изменять без ущерба для производительности. Эти классы похожи, практически двойники, они имеют одинаковые конструкторы, одни и те же методы, которые одинаково используются. Единственное их различие состоит в том, что класс StringBuffer синхронизированный и потокобезопасный. То есть класс StringBuffer удобнее использовать в многопоточных приложениях, где объект данного класса может меняться в различных потоках. Если же речь о многопоточных приложениях не идет, то лучше использовать класс StringBuilder, который не потокобезопасный, но при этом работает быстрее, чем StringBuffer в однопоточных приложениях. Как добавить String в pool строк? Пул строк (string pool) в Java, это некий пул (или список) объектов класса String, который хранится в специальном месте кучи (Java Heap) Сделали для того чтобы оптимизировать выделение памяти и хранение строк, ускорить и оптимизировать работу с ними. Пул строк работает следующим образом: когда мы создаем строку с помощью конструкции String str = "HELLO"; Эта строка попадает в пул строк. Когда мы создаем другую строку с тем же значением: String str2 = "HELLO"; То на самом деле сначала происходит поиск по пулу строк. И если там уже найдена такая строка - то str2 присваивается ссылка на уже созданный объект (на который указывает и str). По этой причине следующая конструкция выведет true (вы же не забыли, что мы работаем не с самими объектами, а со ссылками на них?): String str1 = "abc"; String str2 = "abc"; System.out.println(str1 == str2); Создание строки как нового объектаМеханизм, описанный выше - классный. Он позволяет программисту меньше писать, а JVM использовать меньше памяти и быстрее работать. Но на самом деле мы можем создать объект строки явно, даже в случае, если такая строка уже была создана и записана в пул строк: String str = new String("HELLO"); В этом случае объект будет создан, причем будет создан в куче. Таким образом следующий код: String a = new String("abc"); String b = new String("abc"); System.out.println (a == b); выдаст нам false, ведь ссылки указывают на разные объекты. Поиск по пулу строк тут не происходит. Всё происходящее отлично иллюстрируется следующим изображением, которое я нашел в интернете (кто я такой, чтобы что-то рисовать, хаха): Метод intern() класса StringПри создании объекта для новой строки через оператор new мы можем также попросить JVM поискать эту строку в пуле строк с помощью метода intern(), следующим образом: String a = new String("abc").intern(); В данном случае, если у нас уже есть такая строка в пуле строк, то будет возвращена ссылка на строку из пула строк, и новый объект создан не будет. Логические операторы Логические операции выполняются с помощью логических операторов Логические операции следующие логическое отрицание логическое и логическое или строгое или Отличие операторов сокращенных логических операторов и полных тоже самое что и одиночное но если операнд слева от и false данный операнд возвращает false без проверки второго операнда тоже самое что и одиночное или но если операнд слева является true оператор возвращает true без проверки второго Оператор XOR. Представить таблицу истинности для него Строгое или - если два операнда похожи будет false true true - false false true - true true false - true false false - false Что такое char? Символьный тип данных Хранит одиночный символ в кодировке utf- 16 Почему над ним можно выполнять арифметические операции? Переменной символьного типа можно присвоить целочисленное значение от 0 до 65к целочисленное значение будет указывать на номер символа. Какая размерность у boolean В стандартной реализации Sun JVM и Oracle HotSpot JVM тип boolean занимает 4 байта (32 бита), как и тип int. Однако, в определенных версиях JVM имеются реализации, где в массиве boolean каждое значение занимает по 1-му биту Размер Boolean переменной зависит от виртуальной машины. Какие классы-обертки знаешь? Обертка — это специальный класс, который хранит внутри себя значение примитива. Но поскольку это именно класс, он может создавать свои экземпляры. Они будут хранить внутри нужные значения примитивов, при этом будут являться настоящими объектами. Названия классов-оберток очень похожи на названия соответствующих примитивов, или полностью с ними совпадают. Поэтому запомнить их будет очень легко. Классы-обертки позволяют нивелировать недостатки, которые есть у примитивных типов. Самый очевидный из них — примитивы не имеют методов. Что такое Autoboxing, unboxing и когда они происходят автоматически? Примитивы не являются объектами. Но при этом переменной класса-обертки можно присваивать значение примитивного типа. Этот процесс называется автоупаковкой (autoboxing). Точно так же переменной примитивного типа можно присваивать объект класса-обертки. Этот процесс называется автораспаковкой (autounboxing). Инкременты, декременты, отличия. Инкремент — это операция во многих языках программирования, которая выполняет увеличение переменной. Чаще всего под инкрементом подразумевается увеличение переменной на 1 единицу. Обратной операцией называют декремент. Декремент — это уменьшение переменной. Чаще всего также на единицу. В Java инкремент и декремент — это в первую очередь унарные операторы, которые применяются к какой-либо числовой переменной. Инкремент: обозначается двумя знаками плюс "++" и увеличивает значение переменной на 1. Декремент: обозначается двумя знаками минус "--" и уменьшает значение переменной на 1. У инкремента и декремента есть 2 формы — prefix и postfix. О боже что это, подумали вы?) Не пугайтесь: тут тоже все легко. Prefix, или Префиксная форма, описывается перед переменной "++x или --x", изначально икрементирует или декрементирует переменную. Postfix, или Постфиксная форма, описывается после переменной "x++ или x--", икрементирует или декрементирует переменную после вычисления. int a = 5; System.out.println(++a + a--); Что такое continue и break? Оператор break в Java используется в трех случаях. Во-первых, как вы уже видели, он заканчивает последовательность операторов в ветвях оператора switch. Во-вторых, его можно использовать для выхода из цикла. Используя break, вы можете форсировать немедленное завершение цикла, обходя условное выражение и любой остающийся код в теле цикла. Когда оператор break встречается внутри цикла, второй заканчивается и программное управление передается оператору, следующему за ним. Иногда полезно начать очередную итерацию цикла пораньше. То есть нужно продолжить выполнение цикла, но прекратить обработку остатка кода в его теле для данной частной итерации. На самом деле это — goto-переход мимо следующих операций тела в конец блока цикла. Такое действие выполняет оператор continue. В циклах while и do while оператор continue вызывает передачу управления непосредственно условному выражению, которое управляет циклом. В цикле for управление переходит сначала к итерационной части оператора for и затем к условному выражению. Для всех трех циклов любой промежуточный код обходится. Операторы цикла — изменяют нормальное выполнение последовательности цикла в Java. Когда выполнение выходит из своей области, все объекты, которые были созданы автоматически в этой области будут уничтожены. Java поддерживает следующие управляющие операторы цикла.
Где находятся параметры и аргументы метода Но если вдаваться в детали, то я бы сказал наоборот, что s и count - это аргументы метода, а свои значения они получают из параметров вызова Чем отличается метод от функции Методы в Java — это законченная последовательность действий (инструкций), направленных на решение отдельной задачи. По сути, это функции (они же процедуры, подпрограммы) более ранних, не ООП языков. Только эти функции являются членами классов и для различия с обычными функциями, согласно терминологии объектно-ориентированного программирования, называются методами.Простой способ запомнить: F unction → F ree (Свободные означает не принадлежность к объекту или классу) M ethod → M ember (член объекта или класса) Функция это самостоятельная сущность. Метод это часть класса(объекта) и без него не употребляется. Что такое литерал. Литералы — это явно заданные значения в коде программы — константы определенного типа, которые находятся в коде в момент запуска. В соответствии с примитивами, литералы также делятся на разделы: Числовые: Целочисленные; С плавающей точкой; Строковые; Символьные; Логические. В Java поддерживается 4 системы счисления: Двоичная Восьмеричная Десятичная Шестнадцатеричная Строковые литералы — это набор символов, заключенных в двойные кавычки. Данный тип используется так же часто, как и числовые литералы. В строке также могут находится служебные символы, которые необходимо экранировать (так называемые escape-последовательности). Символьные литералы в Java представлены кодовой таблицей Unicode, то есть каждый символ — 16-битовое значение. Для обозначения символа в коде его обособляют одинарными кавычками. По опыту использования бывают два вида символов: Те, что можно ввести с клавиатуры — обычные символы; Символы, которые просто так с клавиатуры не ввести (символы различных языков, фигуры и так далее). Обычные символы можно указать в явном виде: ‘,’ или ‘@’ Самый простой литерал — это логический. Имеется всего 2 значения: false и true что такое NaN? NaN – Not-a-Number (не число). Его используют в различных ситуациях: 1) Строку конвертируем в число, а в ней есть буквы. Ответ – NaN 2) Бесконечность минус бесконечность. Ответ — NaN 3) Многие другие ситуации, где в ответе ждут число, а получается неизвестно что Почему не рекомендуются множественные конкатенации String? В силу неизменности класса String в результате каждой операции создаются новые экземпляры строк порождая большое количество мусора что происходит при преобразовании int в byte произойдет отсечение Какие данные мы рискуем потерять при приведении char в short? Если значение char входит в диапазон short то ничего не произойдет Переведи число X (любое) из десятичной в двоичную, и число Y (любое) из двоичной в десятичную int i = 232; //число 232 в двоичной системе System.out.println(Integer.toBinaryString(i)); //обратыный перевод из двоичной системы в десятичную System.out.println(Integer.parseInt("11101000", 2)); какого типа данные получатся если сложить long и float float Что такое рекурсия? Рекурсией называется такая конструкция, при которой функция вызывает саму себя. Различают прямую и косвенную рекурсии. Функция называется прямо рекурсивной, если содержит в своем теле вызов самой себя. Если же функция вызывает другую функцию, которая в свою очередь вызывает первую, то такая функция называется косвенно рекурсивной. Недостатки и преимущества? По большей части рекурсия происходит медленнее и занимает больше места в стеке. Основное преимущество рекурсии заключается в том, что для таких задач, как обход дерева, она делает алгоритм немного проще или более "elegant" рекурсивных вызовов негативно скажется на производительности и потребляемой памяти: стек вызовов – практически неконтролируемый ресурс и при разных условиях вызова одной и той же рекурсивной функции, мы можем получить или не получить проблемы, связанные с этим ресурсом. 2 случая (правила/условия) в рекурсивном алгоритме? Эта функция будет считать до бесконечности. Так что, если Вы вдруг запустили код с бесконечным циклом, остановите его сочетанием клавиш «Ctrl-C». (Или, работая к примеру в CodePen, это можно сделать, добавив “?turn_off_js=true” в конце URL.) Рекурсивная функция всегда должна знать, когда ей нужно остановиться. В рекурсивной функции всегда есть два случая: рекурсивный и граничный случаи. Рекурсивный случай – когда функция вызывает саму себя, а граничный – когда функция перестает себя вызывать. Наличие граничного случая и предотвращает зацикливание. Какие есть циклы в Java? Циклы — это разновидность управляющих конструкций для организации многократного выполнения одного и того же участка кода. Код внутри такой управляющей конструкции выполняется циклично. Каждое выполнение кода — это итерация цикла. Количество итераций регулируется условием цикла. Код, который выполняется внутри цикла, называют телом цикла. Известны такие виды циклов: Циклы с предусловием while Повторяет оператор или группу операторов, пока заданное условие является true. Цикл проверяет условие до выполнения тела цикла while (expression) { statement(s) } Здесь: expression — условие цикла, выражение, которое должно возвращать boolean значение. statement(s) — тело цикла (одна или более строк кода). Перед каждой итерацией будет вычисляться значение выражения expression. Если результатом выражения будет true, выполняется тело цикла — statement(s). Циклы со счетчиком for Выполняет последовательность операторов несколько раз и сокращает код, которым управляет переменная цикла когда Вы заранее знаете сколько раз повторится одно и то же действие, -необходимо использовать цикл for Циклы с постусловием do..while условие выполнения определяется после первой итерации (поэтому они всегда выполняются минимум один раз). Полезны, когда нужно выполнять некое действие, пока не реализуется некое условие: например, считывать ввод пользователя, пока он не введет слово “stop” Цикл do...while еще называют цикл "делать до тех пор пока" Цикл разновидность for each Этот цикл Java — разновидность цикла for для итерации коллекций и массивов. Структура for each выглядит так: for (Type var : vars) { statement(s) } Здесь: vars — переменная, существующий список или массив Type var — определение новой переменной того же типа (Type), что и коллекция vars. Данную конструкцию можно прочитать так: “Для каждого var из vars сделать...”. Чем отличаются друг от друга? Как видите, цикл for each не требует ручного изменения переменной - шага для перебора. Цикл автоматически выполняет эту работу. Так что цикл for each очень удобный, когда Вам необходимо вывести на экран все элементы массива/коллекции или перезаписать все элементы с одного массива/коллекции в другой. что такое массив? Массив — это структура данных, в которой хранятся элементы одного типа. Его можно представить, как набор пронумерованных ячеек, в каждую из которых можно поместить какие-то данные (один элемент данных в одну ячейку). Доступ к конкретной ячейке осуществляется через её номер. Номер элемента в массиве также называют индексом. Для чего он нужен? Какая максимальная длина массива? 2^31 2147483647 Что такое массив и какие на нём есть ограничения? Он хранит данные строго определенного типа. Если мы изначально создали массив строк String, мы не сможем хранить в нем что-то другое. Тип данных указывается при создании массива. В этом его отличие от банковской ячейки, в которой клиент может хранить что захочет. Массив может хранить в себе данные примитивных типов (например, int), строки (String) или объекты одного класса. Точнее даже не сами объекты, а ссылки на эти объекты. Размер массива обязательно указывается при создании. Указать его позже или изменить размер после создания не получится. int numbers [] = {7, 12, 8, 4, 33, 79, 1, 16, 2}; Этот способ называется “быстрой инициализацией”. Он довольно удобен тем, что мы сразу создаем массив и заполняем его значениями. Массив объектов JavaCat[] cats = new Cat[3]; cats[0] = new Cat("Томас"); cats[1] = new Cat("Бегемот"); cats[2] = new Cat("Филипп Маркович"); Здесь нужно понимать несколько вещей: В случае с примитивами массивы Java хранят множество конкретных значений (например, чисел int). В случае с объектами массив хранит множество ссылок. Массив cats состоит из трех ячеек, в каждой из которых есть ссылка на объект Cat. Каждая из ссылок указывает на адрес в памяти, где этот объект хранится. Элементы массива в памяти размещаются в едином блоке. Это сделано для более эффективного и быстрого доступа к ним. Таким образом, ссылка cats указывает на блок в памяти, где хранятся все объекты — элементы массива. А cats[0] — на конкретный адрес внутри этого блока. Максимальная размерность многомерного массива 255 Почему 0.1 + 0.7 != 0.8 ? Дело в том, что в двоичной системе невозможно точно представить число 0,1. В десятичной системе, кстати, тоже есть подобная проблема: в ней нельзя правильно представить дроби (и вместо ⅓ мы получим 0.33333333333333 Подобные ошибки связанны с внутренним двоичным (binary) представлением чисел. Подобно тому, как в десятичной системе нельзя точно представить результат деления 1/3, так и в двоичной системе невозможно точно представить 1/10 Для чего нужен пул примитивов? Наверняка вам известно, что при сравнении двух объектов в Java на == обычно получается не тот результат, что нужен, т.к. идет сравнение ссылок на объекты, а не данных этих объектов. Хм, давайте тогда посмотрим на следующий код и на результат его выполнения: public class Temp { public static void main(String []args){ Integer i1 = 10; Integer i2 = 10; System.out.println(i1 == i2); } } Как думаете, что он напечатает? А напечатает он true. А вот еще один код: public class Temp { public static void main(String []args){ Integer i1 = 130; Integer i2 = 130; System.out.println(i1 == i2); } } Этот код уже выведет false. На первый взгляд странно, не так ли? Сейчас объясню. В Java есть пул(pool) целых чисел в промежутке [-128;127]. Т.е. если мы создаем Integer в этом промежутке, то вместо того, чтобы каждый раз создавать новый объект, JVM берет их из пула. Таким образом, в первом примере i1 и i2 указывают на один и тот же объект из пула, а во втором - создаются два разных объекта. Отсюда и результат. Стоит заметить, что в приведенных выше примерах не использовалось ключевое слово new. Пример: public class Temp { public static void main(String []args){ Integer i1 = new Integer(10); Integer i2 = new Integer(10); System.out.println(i1 == i2); } } Результатом будет false. Тут мы уже явно говорим, что хотим создать новый(new) объект, так что ссылки разные. Вот и всё. тернарный оператор Это альтернатива условному оператору if-else Так и выглядит работа этого оператора. Тернарным (тройным) его называют потому, что в его работе принимают участие 3 компонента: Одно условие (man.getAge() >= 18) Два возможных результата ("Все в порядке, проходите!" и "Этот фильм не подходит для вашего возраста!") Вначале в коде записывается условие, после которого ставится вопросительный знак. man.getAge() >= 18 ? |