|
Ревью. Примитивы. Ревью Примитивные типы в Java
РЕВЬЮ: Примитивные типы в Java:
Bit - Binary Digit - двоичная цифра
Byte - знаковый 8-битный тип. Диапозон от -128 до + 127. 128 не сделать, так как в двоичном коде первая цифра это знак, если написать число после 0111 1111, то это уже будет -128. С Byte необязательно будет потребляться меньше памяти (если только в массивах). Связано это с JVM, она приводит Byte и short к 32 битному int, так как системы в основном 32/64 разрядные. Short - увеличенный в два раза Byte. 16 бит. Диапозон от -32768 до +32767. Используется редко. JavaDoc - you can use a short to save memory in large arrays. INT - самый часто используемый. 32 бита (4 байта).Диапазон значений от -2^31 до 2^31 – 1. Максимальное значение int 2147483648 – 1. При вычислении остаток отбрасывается ( 11 / 4 = 2) LONG - диапозон -2^63 до 2^63 – 1. Используется при работе со временем или большим расстоянием. Для обозначения того, что число это long после числа ставят литерал L. Очень часто используется как ID при работе с БД. FLOAT и DOUBLE - нецелочисленные типы (с плавающей точкой). Float - 32 бита, double - 64 бита. Деньги в float и double не надо вычислять (javadoc - This data type should never be used for precise values, such as currency. For that, you will need to use the java.math.BigDecimal class instead.Numbers and Strings covers BigDecimal and other useful classes provided by the Java platform.). При делении на ноль - вернут бесконечность (плюс или минус). При сложении минус бесконечности и плюс - выведет NaN (not a Number). BOOLEAN - может принимать значения только true или false. Используется в логических операциях, таких как циклы while, и в ветвлении при помощи if, switch. Теоретически, нам достаточно 1 бита информации, 0 или 1, то есть true или false. Но на самом деле Boolean будет занимать больше памяти и это будет зависеть от конкретной реализации JVM. Обычно на это тратится столько же, сколько на int. CHAR - данные в char занимают 16 бит и описывают символ. В Java для char используется кодировка Unicode. Символ можно задать в соответствии с двумя таблицами : Таблица Unicode символов и Таблица символов ASCII
Литерал - это по факту значение, которое мы присваиваем переменной. Например int i = 5; 5 - литерал переменной int. Что такое явные и неявные приведения, с чем связано их наличие?
Литералы — это явно заданные значения в коде программы — константы определенного типа, которые находятся в коде в момент запуска.
В соответствии с примитивами, литералы также делятся на разделы:
Числовые:
Целочисленные; С плавающей точкой;
Строковые; Символьные; Логические.
Неявное преобразование типов выполняется в случае, если выполняются условия:
Оба типа совместимы Длина целевого типа больше или равна длине исходного типа
Во всех остальных случаях должно использоваться явное преобразование типов.
Так же существуют два типа преобразований:
Расширяющее преобразование-выполняется автоматически при преобразовании меньшего по размеру типа в больший: byte в short в char в int в long в float в double Сужающее преобразование-выполняется вручную при преобразовании большего по размеру типа в меньший: double в float в long в int в char в short в byte
Java выполняет расширяющие преобразования автоматически, например, если вы присвоили литерал типа int переменной типа double или значение переменной типа char переменной типа int
.
Сплошные линии обозначают преобразования, выполняемые без потери данных. Штриховые линии говорят о том, что при преобразовании может произойти потеря точности.
Стоит немного пояснить почему, к примеру тип byte не преобразуется автоматически (не явно) в тип char, хотя тип byte имеет ширину 8 бит, а char 16, тоже самое касается и преобразования типа short в char. Это происходит потому, что byte и short знаковые типы данных, а char беззнаковый. Поэтому в данном случае требуется использовать явное приведение типов, поскольку компилятору надо явно указать что вы знаете чего хотите и как будет обрабатываться знаковый бит типов byte и short при преобразовании к типу char. Сужающее преобразование (narrowing conversion) происходит, если значение преобразуется в значение типа, диапазон которого не шире изначального. Сужающие преобразования не всегда безопасны: например, преобразование целого значения 13 в byte имеет смысл, а преобразование 13000 в byte неразумно, поскольку byte может хранить только числа от −128 до 127. Поскольку во время сужающего преобразования могут быть потеряны данные, Java компилятор возражает против любого такого преобразования, даже если преобразуемое значение укладывается в более узкий диапазон указанного типа
Явное преобразование примитивных типов
Оператором явного преобразования типов или точнее говоря приведения типов являются круглые скобки, внутри которых указан тип, к которому происходит преобразование – (type).
Слишком большое дробное число при приведении к целому превращается в MAX_VALUE или MIN_VALUE.
Слишком большой double при приведении к float превращается в Float.POSITIVE_INFINITY или Float.NEGATIVE_INFINITY.
byte b2 = 50;
b2 = b2 * 2; // не скомпилируется
b2 *= 2; //скомпилируется, хотя и равнозначна b2 = b2 * 2
Вторя строка, приведенная в примере не скомпилируется из-за автоматического расширения типов в выражениях, так как выражение b2*2 имеет тип int, так как происходит автоматическое расширение типа (целочисленные литералы в выражении всегда int). Третья же строка спокойно скомпилируется, так как в ней сработает неявное приведение типов в совмещенном выражении присваивания. при перекладывании значения из short в char, всегда будут теряться значения меньше 0. При перекладывании из char в short будут теряться значения больше 32-х тысяч Boxing/unboxing – преобразование примитивных типов в объекты обертки
По существу boxing и unboxing это преобразование примитивных типов в объекты обертки и обратно.
Для объектов оберток примитивных типов применимо все что было сказано выше.
Так вот, для каждого примитивного типа есть его старший брат, и он совсем не примитивный, а является настоящим классом, с полями и методами. И для каждой такой парочки возможно автоматическое преобразование.
Благодаря автораспаковке, мы смело можем писать выражения, не используя методы конвертации. Теперь за этим следит компилятор Java.
Так же следует помнить, что автоупаковка и автораспаковка не работает для массивов.
Классы-обёртки неизменяемые, поэтому при каждой автоупаковке (за исключением значений из pool) создается новый объект, что может привести к неразумному расходу памяти. Логические операции в Java
Логический операнд — это выражение, о котором можно сказать что оно является истинным или ложным, true или false. Говоря языком Java, логический операнд — это выражение типа boolean или Boolean, например:
(2 < 1) — логический операнд, его значение равно false true — логический операнд, значение которого, очевидно, true boolean a — тоже может быть логическим операндом, как и Boolean a int a = 2 — не является логическим операндом, это просто переменная типа int String a = "true" также не является логическим операндом. Это строка, текстовое значение которой — "true".
В Java доступны следующие логические операции:
Логическое отрицание, оно же NOT или инверсия. В Java обозначается символом “!” перед операндом. Применяется к одному операнду. Логическое и, оно же AND или конъюнкция. Обозначается символом “&” между двумя операндами, к которым применяется. Логическое или в Java, оно же — OR, оно же — дизъюнкция. В Java обозначается символом “|” между двумя операндами. Исключающее или, XOR, строгая дизъюнкция. В Java обозначается символом “^” между двумя операндами. В Java к логическим операторам можно отнести условное или, обозначаемое как ||, а также условное и — &&.
Как и в математике, в программировании у операторов есть определённый порядок выполнения, если они встречаются в одном выражении. Унарные операторы имеют преимущества над бинарными, а умножение (даже логическое) над сложением.
Мы расположили логические операторы в списке тем выше, чем выше их приоритет:
! & ^ | && ||
операторы &, | и ^ можно употреблять по отношению к целочисленным типам Java. В таком случае они являются поразрядными операторами. Их также называют побитовыми, поскольку один разряд — это и есть один бит, а эти операции работают именно с битами.
Помимо &, | и ^ в Java также используются поразрядные операторы:
поразрядный оператор отрицания >> побитовый сдвиг вправо >>> беззнаковый побитовый сдвиг вправо << побитовый сдвиг влево Что такое пул строк в Java? Пул строк (String Pool) — это множество строк в кучи (Java Heap Memory). Мы знаем, что String — особый класс в java, с помощью которого мы можем создавать строковые объекты.
Сам строковый пул возможен только потому, что строки в Java неизменные. Также пул строк позволяет сохранить память в Java Runtime, хотя это и требует больше времени на создание самой строки.
Когда мы используем двойные кавычки, чтобы создать новую строку, то первым делом идет поиск строки с таким же значением в пуле строк. Если java такую строку нашла, то возвращает ссылку, в противном случае создается новая строка в пуле, а затем возвращается ссылка.
Однако использование оператора new заставляет класс String создать новый объект String. После этого можем использовать метод intern(), чтобы поместить этот объект в пул строк или обратиться к другому объекту из пула строк, который имеет такое же значение.
Что же даёт нам String pool? У этого есть несколько преимуществ:
Не будут создаваться однотипные объекты Сравнение по ссылке быстрее, чем посимвольное сравнение через equals
Java Heap память Java Heap (куча) используется Java Runtime для выделения памяти под объекты и JRE классы. Создание нового объекта также происходит в куче. Здесь работает сборщик мусора: освобождает память путем удаления объектов, на которые нет каких-либо ссылок. Любой объект, созданный в куче, имеет глобальный доступ и на него могут ссылаться с любой части приложения.
Stack память в Java Стековая память в Java работает по схеме LIFO (Последний-зашел-Первый-вышел). Всякий раз, когда вызывается метод, в памяти стека создается новый блок, который содержит примитивы и ссылки на другие объекты в методе. Как только метод заканчивает работу, блок также перестает использоваться, тем самым предоставляя доступ для следующего метода.
Размер стековой памяти намного меньше объема памяти в куче.
Разница между Stack и Heap памятью в Java Куча используется всеми частями приложения в то время как стек используется только одним потоком исполнения программы. Всякий раз, когда создается объект, он всегда хранится в куче, а в памяти стека содержится ссылка на него. Память стека содержит только локальные переменные примитивных типов и ссылки на объекты в куче. Объекты в куче доступны с любой точки программы, в то время как стековая память не может быть доступна для других потоков. Управление памятью в стеке осуществляется по схеме LIFO. Стековая память существует лишь какое-то время работы программы, а память в куче живет с самого начала до конца работы программы. Мы можем использовать -Xms и -Xmx опции JVM, чтобы определить начальный и максимальный размер памяти в куче. Для стека определить размер памяти можно с помощью опции -Xss . Если память стека полностью занята, то Java Runtime бросает java.lang.StackOverflowError, а если память кучи заполнена, то бросается исключение java.lang.OutOfMemoryError: Java Heap Space. Размер памяти стека намного меньше памяти в куче. Из-за простоты распределения памяти (LIFO), стековая память работает намного быстрее кучи.
Размер стринг пула 60000 байт где то у Java8.
Особенность Integer pool в том, что он хранит только размер байта - -128 до +127. Для остальных числе пул не работает.
Prefix, или Префиксная форма, описывается перед переменной "++x или --x", изначально икрементирует или декрементирует переменную.
Postfix, или Постфиксная форма, описывается после переменной "x++ или x--", икрементирует или декрементирует переменную после вычисления.
Методы в Java — это законченная последовательность действий (инструкций), направленных на решение отдельной задачи. По сути, это функции (они же процедуры, подпрограммы) более ранних, не ООП языков. Только эти функции являются членами классов и для различия с обычными функциями, согласно терминологии объектно-ориентированного программирования, называются методами.Простой способ запомнить: F unction → F ree (Свободные означает не принадлежность к объекту или классу) M ethod → M ember (член объекта или класса)
Функция это самостоятельная сущность. Метод это часть класса(объекта) и без него не употребляется.
Условные операторы:
if, if-else и switch-case
Циклы:
Хотя foreach может обходить массивы или коллекции, его можно использовать только для обхода. Он не может изменять массивы или коллекции во время процесса обхода, в то время как цикл for может изменять исходные массивы или коллекции во время процесса обхода.
Foreach имеет хорошую производительность при обходе массивов и коллекций.
final для класса - класс нельзя наследовать,
Максимальная величина массива - 255
final для метода - метод нельзя переопределять, final для переменной - нельзя изменять первое присвоенное значение (сразу присваивать не обязательно), имя пишется капсом, слова через нижний пробел. Объекты всех классов обёрток, StackTrace, а также классы, используемые для создания больших чисел BigInteger и BigDecimal неизменяемые. Таким образом, при создании или изменении строки, каждый раз создаётся новый объект. Строки:
При prinf - %s, “String” вставит на место %s строку.
%d вставит цифру в строку - тут можно задать длину цифры после процента
%f - вставит флоат Рекурсией называется такая конструкция, при которой функция вызывает саму себя. Различают прямую и косвенную рекурсии. Функция называется прямо рекурсивной, если содержит в своем теле вызов самой себя. Если же функция вызывает другую функцию, которая в свою очередь вызывает первую, то такая функция называется косвенно рекурсивной.
По большей части рекурсия происходит медленнее и занимает больше места в стеке. Основное преимущество рекурсии заключается в том, что для таких задач, как обход дерева, она делает алгоритм немного проще или более "elegant".
Рекурсивная функция всегда должна знать, когда ей нужно остановиться. В рекурсивной функции всегда есть два случая: рекурсивный и граничный случаи. Рекурсивный случай – когда функция вызывает саму себя, а граничный – когда функция перестает себя вызывать. Наличие граничного случая и предотвращает зацикливание. Чтобы создать immutable класс нужно, чтобы все поля были private.
Значение должно быть присвоено внутри класса, не должно быть сеттеров, только геттеры. Ссылочный объект нужно клонировать методом .clone Массивы
Массив — это структура данных, в которой хранятся элементы одного типа.
Номер элемента в массиве также называют индексом.
Как и любой другой объект, создать массив Java, то есть зарезервировать под него место в памяти, можно с помощью оператора new:
Int [] i = new int [5];
Int [] i2 = {1, 2, 3, 4, 5} длина массива — это количество элементов, под которое рассчитан массив. Длину массива нельзя изменить после его создания.
Вывести на экран можно через цикл for В двумерных массивах, чтобы получить значение, необходимо обратиться по двум индексам (как в матрице - по горизонтали и по вертикале).
Из двоичной в десятичную:
Вещественные числа состоит из целой части, дробной части и знака. У положительных чисел знак обычно не указывают явно, а у отрицательных указывают. |
|
|