Перейти к содержимому

Как объявить byte число в java

  • автор:

Преобразование массива байтов в числовое представление в Java

В этом руководстве мы рассмотрим различные подходы к преобразованию массива байтов в числовое значение ( int , long , float , double ) и наоборот.

Байт является основной единицей информации в компьютере для хранения и обработки. Примитивные типы, определенные в языке Java, представляют собой удобный способ манипулирования несколькими байтами одновременно. Следовательно, между массивом байтов и примитивными типами существует неотъемлемая связь преобразования .

Поскольку типы short и char состоят всего из двух байтов, они не требуют особого внимания. Итак, мы сосредоточимся на преобразовании между байтовым массивом и типами int , long , float и double .

2. Использование операторов сдвига​

Самый простой способ преобразовать массив байтов в числовое значение — использовать операторы сдвига .

2.1. Byte Array to int и long ​

При преобразовании массива байтов в значение int мы используем оператор

 int value = 0;   for (byte b : bytes)    value = (value  <8) + (b & 0xFF);   > 

Обычно длина массива байтов в приведенном выше фрагменте кода должна быть равна или меньше четырех. Это потому, что значение int занимает четыре байта. В противном случае это приведет к переполнению диапазона int .

Для проверки правильности преобразования определим две константы:

 byte[] INT_BYTE_ARRAY = new byte[]    (byte) 0xCA, (byte) 0xFE, (byte) 0xBA, (byte) 0xBE   >;   int INT_VALUE = 0xCAFEBABE; 

Если мы внимательно посмотрим на эти две константы, INT_BYTE_ARRAY и INT_VALUE , мы обнаружим, что они представляют собой разные представления шестнадцатеричного числа 0xCAFEBABE .

Затем давайте проверим правильность этого преобразования:

 int value = convertByteArrayToIntUsingShiftOperator(INT_BYTE_ARRAY);    assertEquals(INT_VALUE, value); 

Точно так же при преобразовании массива байтов в длинное значение мы можем повторно использовать приведенный выше фрагмент кода с двумя изменениями: тип значения — long , а длина байтов должна быть равна или меньше восьми.

2.2. int и long в байтовый массив​

При преобразовании значения int в массив байтов мы можем использовать оператор >> (знаковый сдвиг вправо) или >>> (беззнаковый сдвиг вправо):

 byte[] bytes = new byte[Integer.BYTES];   int length = bytes.length;   for (int i = 0; i  length; i++)    bytes[length - i - 1] = (byte) (value & 0xFF);   value >>= 8;   > 

В приведенном выше фрагменте кода мы можем заменить оператор >> на оператор >>> . Это потому, что мы используем только те байты, которые изначально содержит параметр value . Таким образом, сдвиг вправо с расширением знака или расширением нуля не повлияет на конечный результат.

Затем мы можем проверить правильность приведенного выше преобразования:

 byte[] bytes = convertIntToByteArrayUsingShiftOperator(INT_VALUE);    assertArrayEquals(INT_BYTE_ARRAY, bytes); 

При преобразовании длинного значения в массив байтов нам нужно только изменить Integer.BYTES на Long.BYTES и убедиться, что тип значения — long .

2.3. Массив байтов для плавания и удвоения ​

При преобразовании массива байтов в число с плавающей запятой мы используем метод Float.intBitsToFloat () :

 // convert bytes to int   int intValue = 0;   for (byte b : bytes)    intValue = (intValue  <8) + (b & 0xFF);   >    // convert int to float   float value = Float.intBitsToFloat(intValue); 

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

Для проверки правильности преобразования определим две константы:

 byte[] FLOAT_BYTE_ARRAY = new byte[]    (byte) 0x40, (byte) 0x48, (byte) 0xF5, (byte) 0xC3   >;   float FLOAT_VALUE = 3.14F; 

Затем давайте проверим правильность этого преобразования:

 float value = convertByteArrayToFloatUsingShiftOperator(FLOAT_BYTE_ARRAY);    assertEquals(Float.floatToIntBits(FLOAT_VALUE), Float.floatToIntBits(value)); 

Точно так же мы можем использовать промежуточное длинное значение и метод Double.longBitsToDouble() для преобразования массива байтов в двойное значение .

2.4. float и double для массива байтов​

При преобразовании числа с плавающей запятой в массив байтов мы можем воспользоваться методом Float.floatToIntBits() :

 // convert float to int   int intValue = Float.floatToIntBits(value);    // convert int to bytes   byte[] bytes = new byte[Float.BYTES];   int length = bytes.length;   for (int i = 0; i  length; i++)    bytes[length - i - 1] = (byte) (intValue & 0xFF);   intValue >>= 8;   > 

Затем давайте проверим правильность этого преобразования:

 byte[] bytes = convertFloatToByteArrayUsingShiftOperator(FLOAT_VALUE);    assertArrayEquals(FLOAT_BYTE_ARRAY, bytes); 

По аналогии мы можем использовать метод Double.doubleToLongBits() для преобразования значения типа double в массив байтов . **

3. Использование байтового буфера ​

Класс java.nio.ByteBuffer предоставляет аккуратный унифицированный способ перевода между массивом байтов и числовым значением ( int , long , float , double ).

3.1. Массив байтов в числовое значение​

Теперь мы используем класс ByteBuffer для преобразования массива байтов в значение типа int :

 ByteBuffer buffer = ByteBuffer.allocate(Integer.BYTES);  buffer.put(bytes);  buffer.rewind();   int value = buffer.getInt(); 

Затем мы используем класс ByteBuffer для преобразования значения int в массив байтов :

 ByteBuffer buffer = ByteBuffer.allocate(Integer.BYTES);  buffer.putInt(value);  buffer.rewind();   byte[] bytes = buffer.array(); 

Следует отметить, что приведенные выше два фрагмента кода следуют одному и тому же шаблону:

  • Во-первых, мы используем метод ByteBuffer.allocate(int) для получения объекта ByteBuffer с указанной емкостью.
  • Затем мы помещаем исходное значение ( массив байтов или значение int ) в объект ByteBuffer , например методы buffer.put(bytes) и buffer.putInt(value) .
  • После этого мы сбрасываем позицию объекта ByteBuffer на ноль, чтобы мы могли читать с самого начала.
  • Наконец, мы получаем целевое значение из объекта ByteBuffer , используя такие методы, как buffer.getInt() и buffer.array() .

Этот шаблон очень универсален и поддерживает преобразование типов long , float и double . Единственная модификация, которую нам нужно сделать, — это информация, относящаяся к типу.

3.2. Использование существующего массива байтов​

Кроме того, метод ByteBuffer.wrap(byte[]) позволяет нам повторно использовать существующий массив байтов без создания нового:

 ByteBuffer.wrap(bytes).getFloat(); 

Однако мы также должны отметить, что длина указанной выше переменной bytes равна или превышает размер целевого типа ( Float.BYTES ). В противном случае будет выброшено BufferUnderflowException .

4. Использование BigInteger ​

Основная цель класса java.math.BigInteger — представлять большие числовые значения, которые в противном случае не поместились бы в примитивный тип данных. Несмотря на то, что мы можем использовать его для преобразования между массивом байтов и примитивным значением, использование BigInteger немного тяжело для таких целей.

4.1. Byte Array to int и long ​

Теперь воспользуемся классом BigInteger для преобразования массива байтов в значение типа int :

 int value = new BigInteger(bytes).intValue(); 

Точно так же класс BigInteger имеет метод longValue() для преобразования массива байтов в длинное значение:

 long value = new BigInteger(bytes).longValue(); 

Кроме того, класс BigInteger также имеет метод intValueExact() и метод longValueExact() . Эти два метода следует использовать осторожно : если объект BigInteger выходит за пределы диапазона типа int или long , соответственно, оба метода вызовут исключение ArithmeticException .

При преобразовании значения int или long в массив байтов мы можем использовать один и тот же фрагмент кода:

 byte[] bytes = BigInteger.valueOf(value).toByteArray(); 

Однако метод toByteArray () класса BigInteger возвращает минимальное количество байтов, не обязательно четыре или восемь байтов.

4.2. Массив байтов для плавания и удвоения ​

Хотя класс BigInteger имеет метод floatValue() , мы не можем использовать его для преобразования массива байтов в значение с плавающей запятой , как ожидалось. Так что нам делать? Мы можем использовать значение int в качестве промежуточного шага для преобразования массива байтов в значение с плавающей запятой :

 int intValue = new BigInteger(bytes).intValue();   float value = Float.intBitsToFloat(intValue); 

Точно так же мы можем преобразовать значение с плавающей запятой в массив байтов :

 int intValue = Float.floatToIntBits(value);   byte[] bytes = BigInteger.valueOf(intValue).toByteArray(); 

Аналогичным образом, воспользовавшись преимуществами методов Double.longBitsToDouble() и Double.doubleToLongBits() , мы можем использовать класс BigInteger для преобразования между массивом байтов и двойным значением.

5. Использование гуавы​

Библиотека Guava предоставляет нам удобные методы для такого преобразования.

5.1. Byte Array to int и long ​

В Guava класс Ints в пакете com.google.common.primitives содержит метод fromByteArray() . Следовательно, нам довольно легко преобразовать массив байтов в значение int :

 int value = Ints.fromByteArray(bytes); 

Класс Ints также имеет метод toByteArray() , который можно использовать для преобразования значения int в массив байтов :

 byte[] bytes = Ints.toByteArray(value); 

И класс Longs похож в использовании на класс Ints :

 long value = Longs.fromByteArray(bytes);   byte[] bytes = Longs.toByteArray(value); 

Кроме того, если мы проверим исходный код методов fromByteArray() и toByteArray() , то обнаружим, что оба метода используют операторы сдвига для выполнения своих задач .

5.2. Массив байтов для плавания и удвоения ​

В том же пакете также существуют классы Floats и Doubles . Но ни один из этих двух классов не поддерживает методы fromByteArray() и toByteArray() .

Однако мы можем использовать методы Float.intBitsToFloat() , Float.floatToIntBits() , Double.longBitsToDouble() и Double.doubleToLongBits() для завершения преобразования между массивом байтов и значением с плавающей запятой или двойным значением. Для краткости мы опустили здесь код.

6. Использование CommonsLang​

Когда мы используем Apache Commons Lang 3 , выполнять такие преобразования немного сложно. Это связано с тем, что библиотека Commons Lang по умолчанию использует массивы байтов с прямым порядком байтов . Однако все массивы байтов , о которых мы упоминали выше, имеют порядок байтов с обратным порядком байтов. Таким образом, нам нужно преобразовать массив байтов с прямым порядком байтов в массив байтов с прямым порядком байтов и наоборот.

6.1. Byte Array to int и long ​

Класс Conversion в пакете org.apache.commons.lang3 предоставляет методы byteArrayToInt() и intToByteArray() .

Теперь давайте преобразуем массив байтов в значение int :

 byte[] copyBytes = Arrays.copyOf(bytes, bytes.length);   ArrayUtils.reverse(copyBytes);   int value = Conversion.byteArrayToInt(copyBytes, 0, 0, 0, copyBytes.length); 

В приведенном выше коде мы делаем копию исходной переменной bytes . Это связано с тем, что иногда мы не хотим изменять содержимое исходного массива байтов .

Затем давайте преобразуем значение int в массив байтов :

 byte[] bytes = new byte[Integer.BYTES];   Conversion.intToByteArray(value, 0, bytes, 0, bytes.length);   ArrayUtils.reverse(bytes); 

Класс Conversion также определяет методы byteArrayToLong() и longToByteArray() . И мы можем использовать эти два метода для преобразования массива байтов в длинное значение.

6.2. Массив байтов для плавания и удвоения ​

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

Опять же, нам нужно промежуточное целочисленное или длинное значение для преобразования между массивом байтов и значением с плавающей запятой или двойным значением.

7. Заключение​

В этой статье мы проиллюстрировали различные способы преобразования массива байтов в числовое значение, используя простую Java с помощью операторов сдвига, ByteBuffer и BigInteger . Затем мы увидели соответствующие преобразования с использованием Guava и Apache Commons Lang.

Как обычно, исходный код этого руководства можно найти на GitHub .

  • 1. Обзор
  • 2. Использование операторов сдвига
    • 2.1. Byte Array to int и long
    • 2.2. int и long в байтовый массив
    • 2.3. Массив байтов для плавания и удвоения
    • 2.4. float и double для массива байтов
    • 3.1. Массив байтов в числовое значение
    • 3.2. Использование существующего массива байтов
    • 4.1. Byte Array to int и long
    • 4.2. Массив байтов для плавания и удвоения
    • 5.1. Byte Array to int и long
    • 5.2. Массив байтов для плавания и удвоения
    • 6.1. Byte Array to int и long
    • 6.2. Массив байтов для плавания и удвоения

    Перевод большого числа в byte

    Делаю шифрование с помощью сдвигов битов в байте.Но если байту присвоить значение больше 127, оно начинает терять данные.Как правильно перевести большое число в байты без потери данных или чтобы его можно было потом восстановить?

    Отслеживать
    49.6k 17 17 золотых знаков 57 57 серебряных знаков 101 101 бронзовый знак
    задан 9 дек 2018 в 7:35
    Volodymyr Hovorun Volodymyr Hovorun
    29 5 5 бронзовых знаков

    Никак. Если коротко. Нельзя впихнуть невпихуемое. Так что, нужно большое число разбивать на байты. Для одной переменной int нужно будет 4 переменных byte

    Commented 9 дек 2018 в 8:29

    Привидите пример того что вы делаете, какой результат получаете и каой результат хотелось бы получить.

    Commented 9 дек 2018 в 8:34
    Можно для этого использовать массив
    Commented 9 дек 2018 в 9:23
    Чтобы не терять биты при сдвигах, сдвигать надо циклически.
    Commented 9 дек 2018 в 9:44

    2 ответа 2

    Сортировка: Сброс на вариант по умолчанию

    В Java нет беззнаковых типов, но если вы хотите — можете сымитировать беззнаковый байт uint8 (хранит значения 0. 255), вычитая 256 из чисел больше 127. Так вы будите использовать отрицательную область -128. -1.

    Обратное преобразование int b = Byte.toUnsignedInt(a);

    Это будет работать для чисел до 255. Больше чем 256 значений в один байт положить не получиться.

    Чтобы перевести в байты числа больших размеров берите байты от типов short — 2 байта, int — 4 байта, или long — 8 байт. Отдельные байты можно получить методом битового сдвига.

    Отслеживать
    ответ дан 9 дек 2018 в 9:39
    3,031 7 7 серебряных знаков 16 16 бронзовых знаков

    введите сюда описание изображения

    Думаю для этих целей можно использовать BigInteger. Не думаю, что это оптимальный метод. В java вроде был api для шифрования и есть сторонние библиотеки. BigInteger можно перевести в массив байта путем вызова toByteArray(). Если есть знания английского или гугл переводчика https://docs.oracle.com/javase/7/docs/api/java/math/BigInteger.html В дополнение комментария о сдвигах. В стандартной библиотеке нет циклических сдвигов для Byte. Но можно их реализовать на примере сдвигов для Integer из openjdk. rotateLeft и rotateRight методы.

    Отслеживать
    ответ дан 9 дек 2018 в 19:27
    23 7 7 бронзовых знаков

    • java
    • byte
      Важное на Мете
    Похожие

    Подписаться на ленту

    Лента вопроса

    Для подписки на ленту скопируйте и вставьте эту ссылку в вашу программу для чтения RSS.

    Дизайн сайта / логотип © 2024 Stack Exchange Inc; пользовательские материалы лицензированы в соответствии с CC BY-SA . rev 2024.6.17.11080

    Как объявить byte число в java

    Одной из основных особенностей Java является то, что данный язык является строго типизированным. А это значит, что каждая переменная и константа представляет определенный тип и данный тип строго определен. Тип данных определяет диапазон значений, которые может хранить переменная или константа.

    Итак, рассмотрим систему встроенных базовых типов данных, которая используется для создания переменных в Java. А она представлена следующими типами.

      boolean : хранит значение true или false

    boolean isActive = false; boolean isAlive = true;
    byte a = 3; byte b = 8;
    short a = 3; short b = 8;
    int a = 4; int b = 9;
    long a = 5; long b = 10;
    double x = 8.5; double y = 2.7;
    float x = 8.5F; float y = 2.7F;

    При этом переменная может принимать только те значения, которые соответствуют ее типу. Если переменная представляет целочисленный тип, то она не может хранить дробные числа.

    Целые числа

    Все целочисленные литералы, например, числа 10, 4, -5, воспринимаются как значения типа int , однако мы можем присваивать целочисленные литералы другим целочисленным типам: byte , long , short . В этом случае Java автоматически осуществляет соответствующие преобразования:

    byte a = 1; short b = 2; long c = 2121;

    Однако если мы захотим присвоить переменной типа long очень большое число, которое выходит за пределы допустимых значений для типа int, то мы столкнемся с ошибкой во время компиляции:

    long num = 2147483649;

    Здесь число 2147483649 является допустимым для типа long, но выходит за предельные значения для типа int. И так как все целочисленные значения по умолчанию расцениваются как значения типа int, то компилятор укажет нам на ошибку. Чтобы решить проблему, надо добавить к числу суффикс l или L , который указывает, что число представляет тип long:

    long num = 2147483649L;

    Как правило, значения для целочисленных переменных задаются в десятичной системе счисления, однако мы можем применять и другие системы счисления. Например:

    int num111 = 0x6F; // 16-теричная система, число 111 int num8 = 010; // 8-ричная система, число 8 int num13 = 0b1101; // 2-ичная система, число 13

    Для задания шестнадцатеричного значения после символов 0x указывается число в шестнадцатеричном формате. Таким же образом восьмеричное значение указывается после символа 0 , а двоичное значение — после символов 0b .

    Также целые числа поддерживают разделение разрядов числа с помощью знака подчеркивания:

    int x = 123_456; int y = 234_567__789; System.out.println(x); // 123456 System.out.println(y); // 234567789
    Числа с плавающей точкой

    При присвоении переменной типа float дробного литерала с плавающей точкой, например, 3.1, 4.5 и т.д., Java автоматически рассматривает этот литерал как значение типа double . И чтобы указать, что данное значение должно рассматриваться как float , нам надо использовать суффикс f:

    float fl = 30.6f; double db = 30.6;

    И хотя в данном случае обе переменных имеют практически одно значения, но эти значения будут по-разному рассматриваться и будут занимать разное место в памяти.

    Символы и строки

    В качестве значения переменная символьного типа получает одиночный символ, заключенный в одинарные кавычки: char ch=’e’; . Кроме того, переменной символьного типа также можно присвоить целочисленное значение от 0 до 65535 . В этом случае переменная опять же будет хранить символ, а целочисленное значение будет указывать на номер символа в таблице символов Unicode (UTF-16). Например:

    char ch=102; // символ 'f' System.out.println(ch);

    Еще одной формой задания символьных переменных является шестнадцатеричная форма: переменная получает значение в шестнадцатеричной форме, которое следует после символов «\u». Например, char ch=’\u0066′; опять же будет хранить символ ‘f’.

    Символьные переменные не стоит путать со строковыми, ‘a’ не идентично «a». Строковые переменные представляют объект String , который в отличие от char или int не является примитивным типом в Java:

    String hello = "Hello. "; System.out.println(hello);

    Кроме собственно символов, которые представляют буквы, цифры, знаки препинания, прочие символы, есть специальные наборы символов, которые называют управляющими последовательностями. Например, самая популярная последовательность — «\n». Она выполняет перенос на следующую строку. Например:

    String text = "Hello \nworld"; System.out.println(text);

    Результат выполнения данного кода:

    Hello world

    В данном случае последовательность \n будет сигналом, что необходимо сделать перевод на следующую строку.

    Начиная с версии 15 Java поддерживает тестовые блоки (text blocks) — многострочный текст, облеченный в тройные кавычки. Рассмотрим, в чем их практическая польза. Например, выведем большой многострочный текст:

    String text = "Вот мысль, которой весь я предан,\n"+ "Итог всего, что ум скопил.\n"+ "Лишь тот, кем бой за жизнь изведан,\n"+ "Жизнь и свободу заслужил."; System.out.println(text);

    С помощью операции + мы можем присоединить к одному тексту другой, причем продолжение текста может располагаться на следующей строке. Чтобы при выводе текста происходил перенос на следующую строку, применяется последовательность \n.

    Результат выполнения данного кода:

    Вот мысль, которой весь я предан, Итог всего, что ум скопил. Лишь тот, кем бой за жизнь изведан, Жизнь и свободу заслужил.

    Текстовые блоки, которые появились в JDK15, позволяют упростить написание многострочного текста:

    String text = """ Вот мысль, которой весь я предан, Итог всего, что ум скопил. Лишь тот, кем бой за жизнь изведан, Жизнь и свободу заслужил. """; System.out.println(text);

    Весь текстовый блок оборачивается в тройные кавычки, при этом не надо использовать соединение строк или последовательность \n для их переноса. Результат выполнения программы будет тем же, что и в примере выше.

    Типы

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

    Примитивные типы Java не являются объектами. К ним относятся:

    • boolean — булев тип, может иметь значения true или false
    • byte — 8-разрядное целое число
    • short — 16-разрядное целое число
    • int — 32-разрядное целое число
    • long — 64-разрядное целое число
    • char — 16-разрядное беззнаковое целое, представляющее собой символ UTF-16 (буквы и цифры)
    • float — 32-разрядное число в формате IEEE 754 с плавающей точкой
    • double — 64-разрядное число в формате IEEE 754 с плавающей точкой

    Примитивный в данном случае не оскорбление, а просто даёт понять, что речь идёт о простом типе, который не умеет прыгать, спать или мяукать. Да что он вообще умеет? Ой, всё.

    Простые числовые типы

    Тип Разрядность MIN MAX
    byte 8 бит -128 127
    short 16 бит -32768 32767
    int 32 бит -2147483648 2147483647
    long 64 бит -9223372036854775808 9223372036854775807
    float 32 бит -3.4E+38 3.4E+38
    double 64 бит -1.7E+308 1.7E+308

    Целочисленные типы

    Java определяет четыре целочисленных типа: byte, short, int, long. Они могут быть положительными и отрицательными (Java не поддерживает только положительные значения без знака, как некоторые языки программирования).

    Тип byte

    Наименьший по размеру целочисленный тип — byte. Это 8-битовый тип с диапазоном допустимых значений от -128 до 127. Переменные типа byte часто используются при работе с потоком данных из сети или файла, а также при работе с необработанными двоичными данными или в массивах для экономии памяти.

    Объявить переменную типа byte можно следующим образом:

     byte c, a, t; // объявили сразу три переменные 

    В арифметических выражениях с переменными типа byte вычисления выполняются как с типом int, т.е. с помощью 32-битовой арифметики, а полученный результат будет 32-битовым. Смотри пример с short.

    Строку с числом перевести в данный тип можно через метод parseByte(String):

     byte x = Byte.parseByte("100"); 

    Класс Byte является оболочкой для данного типа. Без необходимости не используйте в Android класс Byte.

    Слово «байт» (byte) возникло в компании IBM примерно в 1956 году. Оно произошло от слова bite («кусок»), но его было решено писать через букву y, чтобы не путать со словом «bit» («бит»). В течение некоторого времени слово «байт» обозначало просто число битов в конкретном потоке данных. Однако в середине 1960-х, в связи с разработкой семейства компьютеров System/360 в компании IBM, это слово стало обозначать группу из восьми бит.

    Любопытно, что bite имеет также значение «укус» (сущ.) или «укусить» (глагол). Таким образом это наш родной «Кусь!»

    Cat

    Тип short

    Тип short — 16-битовый тип в диапазоне от -32768 до 32767. Используется очень редко.

     short m; 

    В арифметических выражениях с переменными типа short вычисления выполняются как с типом int, т.е. с помощью 32-битовой арифметики, а полученный результат будет 32-битовым. Например, такой код не пройдёт.

     // накорми кота short fishNumber = 3; // три рыбки short beefNumber = 2; // два кусочка говядины short breakfast = 0; breakfast = fishNumber + beefNumber; // завтрак чемпиона 

    Java будет ругаться на последнюю строчку, так как итоговый результат не может быть short. Как вариант, вам нужно преобразовать результат снова в 16-битовое число.

     breakfast = (short) (fishNumber + beefNumber); // завтрак чемпиона 

    Явно перевести строку с числом в тип short можно через метод parseShort(String):

     short x = Short.parseShort("100"); 

    Класс Short является оболочкой для данного типа. Без необходимости не используйте в Android класс Short.

    Тип int

    Целые числа, представленные типом int, являются самым распространённым типом в программе, с которым вы будете работать. Поэтому нужно хорошенько изучить его и узнать его достоинства и ограничения. Это 32-битовый тип, имеющий диапазон допустимых значений от -2147483648 до 2147483647 (около двух миллиардов). Этого числа вполне достаточно, чтобы посчитать всех котов на свете. Часто используется в циклах, индексировании массивов, хотя может показаться, что для небольших операций в цикле и массивах проще использовать short или byte. Нужно запомнить, что тип int эффективен в этих случаях из-за особенностей структуры вычислительных процессоров. Просто примите на веру.

    Сказка про тип int

    Зададим себе вопрос, насколько большим может быть целое число типа int?

    Напишем простую программу, где будем умножать переменную саму на себя. Для начала присвоим ей значение 2, а дальше строчка за строчкой будем выводить результат. Результаты будем отдавать коту учёному LogCat. Весь код поместим в обработчик события щелчка на кнопке нашей учебной программы, а первую строчку поместим выше её.

     final String TAG = "ExpressCourse"; public void onClick(View view)

    Запустите программу и нажмите кнопку. В нижней части студии откройте панель Android Monitor и в ней вкладку logcat. Настройте его фильтр, чтобы отображались только наши сообщения. В результате мы получим такую картину:

    2 4 16 256 65536 0 0 0 0

    Странные результаты типа Integer

    Что за бред, скажете вы. Когда мы умножаем 65536 на себя, то получаем 0 (Только не говорите об этом учительнице по математике). А потом, естественно, программа умножает 0 на 0 и продолжает выводить результаты.

    Вы ещё больше удивитесь, если в качестве начального значения возьмёте число 3. На этот раз вы сможете получить даже отрицательные значения.

    3 9 81 6561 43046721 -501334399 2038349057 -1970898431 120648705

    Проверьте самостоятельно. Если вы и это попытаетесь доказать учительнице, то исключение из учебного заведения вам гарантировано.

    Деление целочисленных чисел

    Запомните, что при делении целочисленных чисел остаток отбрасывается. Поэтому следующие примеры вернут один и тот же результат. Бедная учительница, её увезут в психушку.

     6 / 3 = 2 7 / 3 = 2 8 / 3 = 2 9 / 3 = 3 

    На ноль делить нельзя, увидите ошибку.

    Если нужен узнать остаток от деления, то используйте оператор % (оператор деления по модулю).

     Log.d(TAG, "Остаток 6 % 3: " + 6 % 3); // 0 Log.d(TAG, "Остаток 7 % 3: " + 7 % 3); // 1 Log.d(TAG, "Остаток 8 % 3: " + 8 % 3); // 2 Log.d(TAG, "Остаток 9 % 3: " + 9 % 3); // 0 

    Класс Integer является оболочкой для данного типа. Без необходимости не используйте в Android класс Integer. Для сравнения: тип int занимает 4 байт памяти, а Integer — 16 байт.

    Также есть специальный класс BigInteger для проведения арифметических действий повышенной точности (финансовые расчёты).

    В Java 7 можно использовать знак подчёркивания для удобства. Например, так:

     int myInt = 1_000_000; // миллион 

    Компилятор не обращает внимания на эти знаки, а человеку проще понять, что ему предлагают миллион или миллиард. В Android относительно недавно появилась полноценная поддержка Java 7 и вам в настройках нужно указать новую версию компилятора.

    Этот приём относится не только к int, но и к другим типам чисел.

    Как сконвертировать строку или CharSequence в int?
     String mString = "42"; // строка int mInt = Integer.parseInt(mString); 

    Если у вас тип CharSequence, то его можно сконвертировать сначала в строку при помощи метода toString(), а потом в int.

    Метод parseInt() предпочтительнее метода valueOf():

     int number; // плохой вариант number2 = Integer.valueOf("1"); // отличный вариант number = Integer.parseInt("1"); 
    Как сконвертировать число в строку?

    Если сложить число и строку, то Java автоматически конвертирует число в строку. Пользуясь этим свойством, программисты часто прибавляют к числу пустую строку. Но лучше использовать метод valueOf():

     int number = 1; // плохой вариант String numberString = "" + number; // отличный вариант String numberString = String.valueOf(number); 
    Добавить ведущие нули

    Если мы хотим получить строку из числа, добавим при этом несколько нулей вначале, то поможет метод format(), только учитывайте число цифр в самом числе.

     int givenNumber = 777; String formattedNumber = String.format("%06d", givenNumber); System.out.println("Число с ведущими нулями: " + formattedNumber); // Число с ведущими нулями: 000777 

    Тип long

    Тип long — это 64-битный тип со знаком, используемый в тех случаях, когда используется очень большое значение, которое не способен хранить тип int. Например, чтобы вычислить расстояние, которое прошёл солнечный луч от солнца до зеркала, превратившись в солнечного зайчика, за которым безуспешно охотится котёнок, вам понадобится именно этот тип.

    Можно использовать символы l или L для обозначения числа типа long. Рекомендую использовать заглавную букву, чтобы избежать возможной путаницы. Например, напишем пример:

     // сколько ночей в арабских сказках? long night = 101l; System.out.println(night); 

    Запустив пример, вы увидите ответ 101. Почему так получилось? А потому что последний символ — это не единица, а символ l. Присмотритесь внимательнее. Если бы мы написали long night = 101L, то не ломали бы голову себе.

    Конвертируем строку в данный тип.

     long x = Long.parseLong("100"); 

    Класс Long является оболочкой для данного типа. Без необходимости не используйте в Android класс Long.

    Типы с плавающей точкой

    Числа с плавающей точкой (иногда их называют действительными числами) применяются при вычислении выражений, в которых требуется точность до десятичного знака. Например, это может быть вычисление квадратного корня, значений синуса, косинуса и т.п. Существует два типа с плавающей точкой: float и double, которые представляют числа одинарной и двойной точности.

    Слово «плавающая» означает, что десятичная точка может располагаться в любом месте (она «плавает»). Вот коты плавать не особенно любят, поэтому они не float и не double.

    Тип float

    Тип float определяет значение одинарной точности, которое занимает 32 бит. Переменные данного типа удобны, когда требуется дробная часть без особой точности, например, для денежных сумм.

    Рекомендуется добавлять символ F или f для обозначения этого типа, иначе число будет считаться типом double.

     float tugrik = 11.6F; 

    Конвертируем из строки.

     float x = Float.parseFloat("19.95"); 

    Класс Float является оболочкой для данного типа. Без необходимости не используйте в Android класс Float.

    Также есть специальный класс BigDecimal для проведения арифметических действий повышенной точности (финансовые расчёты).

    Тип double

    Тип double обеспечивает двойную точность, что видно из его названия (double — двойная). Занимает 64 бит для хранения значений. Многие математические функции возвращают значения типа double. Кстати, современные процессоры оптимизированы под вычисления значений двойной точности, поэтому они предпочтительнее, чем тип float.

     double pi, r, a; pi = 3.1416; // приблизительное значение числа π r = 5.5; // радиус окружности a = pi * r * r; // вычисляем площадь окружности 

    Тип double содержит не только числа, но и слова. Сейчас вам докажу. Разделим число типа double на ноль. Ошибки не произойдёт.

     double positive_infinity = 12.0 / 0; System.out.println(positive_infinity); 

    Пример вернёт значение Infinity (Бесконечность). Если разделить отрицательное число на ноль, то вернётся -Infinity.

    А что произойдёт, если сложить две бесконечности? Если рассуждать логически, то сломается интернет, наступит конец света или можно вызвать Волдеморта. Я долго не решался, но потом набрался храбрости и попробовал.

     double positive_infinity = 12.0 / 0; double negative_infinity = -15.0 / 0; mInfoTextView.setText(String.valueOf(positive_infinity + negative_infinity)); 

    Вернулось ещё одно слово — NaN. Что это вообще? Может должно вернуться Nyan — ну вы знаете, это странный котик, который летит бесконечно в космосе, оставляя за собой шлейф из радуги.

    Умножать две бесконечности я побоялся. И вам не советую.

    Класс Double является оболочкой для данного типа. Без необходимости не используйте в Android класс Double.

    Конвертация строки в double

    Есть несколько вариантов.

     // если строка null, то будет исключение NullPointerException // если строка содержит неправильные данные, то будет исключение NumberFormatException String s = "435.23"; Double d = Double.valueOf(s); // возвращает не Double, а double (примитивный тип) // выбрасывает аналогичные исключения double x = Double.parseDouble("19.95"); // В Java 9 признан устаревшим. Не используйте и сейчас String s = "135.360"; Double d = new Double(s); // Через DecimalFormat String s = "135.130"; try < DecimalFormat decimalFormat = new DecimalFormat("#"); double d = decimalFormat.parse(s).doubleValue(); System.out.println("Double value for 135.130 is " + d); >catch (ParseException e)

    Конвертация double в строку

    При работе с числами double следует держать ухо востро. Рассмотрим пример конвертации трёх чисел.

     double number1 = 120; double number2 = 0.033; double number3 = 0.000045158458; System.out.println(String.valueOf(number1)); System.out.println(String.valueOf(number2)); System.out.println(String.valueOf(number3)); /* System.out: 120.0 System.out: 0.033 System.out: 4.5158458E-5 */ 

    Первые два числа нормально преобразовались, а вот третье число преобразовалось в строку в странном виде (на самом деле это научное представление числа). И это может источником проблемы при передаче строки куда-нибудь, например, на сервер. Если сервер не ожидает от вас такой подлости, то будет генерировать ошибки из-за странной записи. Нужно найти другие способы конвертации.

    Первый способ — используем String.format().

     double number3 = 0.000045158458; System.out.println(String.valueOf(number3)); System.out.println(String.format("%f", number3)); System.out.println(String.format("%.0f", number3)); System.out.println(String.format("%.12f", number3)); /* System.out: 4.5158458E-5 System.out: 0.000045 System.out: 0 System.out: 0.000045158458 */ 

    Последний пример самый подходящий для нас, но вам нужно знать, сколько знаков идёт после десятичной точки. Остальные два пригодятся, если число можно округлить.

    Второй способ — метод Double.toString(). У меня метод превратил число в «непонятную» строку. А у некоторых этот пример возвращал строку в нормальном виде. Не заслуживает доверия.

     double number3 = 0.000045158458; System.out.println(Double.toString(number3)); /* System.out: 4.5158458E-5 */ 

    Третий способ — добавить пустую строку. В Android не помогло, хотя тоже утверждается, что у кого-то выводится в нормальном виде. Врут, наверное.

     double number3 = 0.000045158458; System.out.println(number3 + ""); /* System.out: 4.5158458E-5 */ 

    Четвёртый экзотический способ, которым редко пользуются — DecimalFormat.

     double number3 = 0.000045158458; String pattern = "##.############"; DecimalFormat decimalFormat = new DecimalFormat(pattern); System.out.println(decimalFormat.format(number3)); /* System.out: 0.000045158458 */ 

    Символы (тип char)

    Для хранения символов Java использует специальный тип char. Он отличается от типа char в языках C/C++, где представляет собой целочисленный тип с размером 8 бит. В Java для char используется кодировка Unicode и для хранения Unicode-символов используется 16 бит или 2 байта. Диапазон допустимых значений — от 0 до 65536 (отрицательных значений не существует).

     char ch1, ch2, ch3; ch1 = 67; // код переменной ch2 = 'a'; // сам символ ch3 = 116; // код переменной mInfoTextView.setText("Слово из трёх букв: " + ch1 + ch2 + ch3); 

    Из примера выше видно, что переменной можно присвоить код символа или непосредственно сам символ, который следует окружить одинарными кавычками. Попробуйте запустить пример и посмотреть, какое слово получится из трёх указанных символов.

    Не следует путать символ ‘a’ со строкой «a», состоящей из одного символа. На экране монитора они выглядят одинаково, но в программах ведут себя по разному.

    Стандартные символы ASCII можно выводить сразу. Если нужно вывести специальный символ из Unicode, то можно воспользоваться шестнадцатеричным представлением кода в escape-последовательности — вы указываете обратную наклонную черту и четыре цифры после u. Например:

     char myChar = '\u0054'; 

    Хотя тип char используется для хранения Unicode-символов, его можно использовать как целочисленный тип, используя сложение или вычитание.

     char ch1; ch1 = 'x'; mInfoTextView.append("ch1 содержит " + ch1); ch1++; // увеличим на единицу mInfoTextView.append("ch1 содержит " + ch1); 

    В результате получим:

     ch1 содержит x ch1 содержит y 

    Если вы думаете, что увеличив значение переменной ch1 ещё на одну единицу, получите символ «й», то глубоко заблуждаетесь.

    Чтобы узнать, какой символ содержится в значении переменной, заданной как int, можно воспользоваться двумя специальными методами из класса EncodingUtils:

    Для стандартных символов ASCII:

     int i = 67; byte[] data = < (byte) i >; CharSequence strSymbol = EncodingUtils.getAsciiString(data); mInfoTextView.setText(strSymbol); 

    Для расширенной таблицы символов:

     int i = 379; byte[] data = < (byte) i >; CharSequence strSymbol = EncodingUtils.getString(data, "windows-1251"); mInfoTextView.setText(strSymbol); 

    Методы работают со строками, но если мы используем строку из одного символа, то получим то, что нам нужно.

    В упрощённом виде, если работаем со стандартными символами ASCII (on 0 до 127), то можно получить символ из int ещё проще.

     int ascii = 65; if(ascii > 127)< System.out.println("Wrong value"); >else

    Класс Character

    Класс Character является оболочкой вокруг типа char. Чтобы получить значение типа char, содержащее в объекте класса Character, вызовите метод charValue().

    С классом Character редко имеют дело в Android, но помните, что класс содержит огромное количество констант и методов. Например, можно определить, является ли символ цифрой или буквой, или написан ли символ в нижнем или в верхнем регистре.

    Булевы значения

    Тип boolean предназначен для хранения логических значений и может принимать только одно из двух возможных значений: true или false. Данный тип всегда возвращается при использовании операторов сравнения (больше, меньше, равно, больше или равно, меньше или равно, не равно). Также он используется в управляющих операторах if и for.

     boolean check; check = true; 

    В отличие от реальной жизни, где вполне может состояться диалог:

    - Кать, чай будешь? - Да нет наверное

    В компьютерной программе нужно чётко определиться — истина или ложь.

    В операторах if используется укороченная запись при значении true:

     if (check == true) . // необязательный вариант if (check) . // укороченная запись 

    Java сам поймёт, что переменную check нужно сравнить с true.

    Класс Boolean

    Класс Boolean является оболочкой вокруг значений типа boolean. Чтобы получить значение типа boolean из объекта класса Boolean, используйте метод booleanValue(). Тип boolean использует 4 байт памяти, а Boolean — 16. Вывод понятен?

    Ещё один совет, применимый ко всем типам. Допустим, нам нужно объявить 32 переменных типа boolean:

     boolean mProperty1; boolean mProperty2; . boolean mProperty32; 

    Умножаем 4 байта на 32 переменных и получаем 128 байт занятой памяти. А если объявим массив:

     boolean[] mProperty = new boolean[32] 

    Считаем: 4 + 8 + 8 + 32 * 1 = 52. С учётом выравнивания памяти по 8 байт, получаем не 52, а 56. Всё равно меньше, чем в первом примере.

    Конвертируем строку в булево значение.

     Boolean booleanValue = Boolean.valueOf("true"); System.out.println(booleanValue); 

    Конвертируем булево значение в строку.

     boolean boolenValue = true; // первый способ System.out.println(Boolean.toString(booleanValue)); // второй способ System.out.println(String.valueOf(booleanValue)); 

    Приведение типов

    Когда мы производим какие-то действия с переменными, то нужно следить за типами. Нельзя умножать котов на футбольные мячи, это противоречит здравому смыслу. Также и с переменными. Если вы присваиваете переменной одного типа значение другого типа, то вспоминайте теорию. Например, вы без проблем можете присвоить значение типа int переменной типа long, так как все числа из диапазона типа int гарантировано помещаются в диапазон чисел long. В этом случае Java выполнит преобразование автоматически, вы даже ничего не заметите.

    Представим обратную картину — мы хотим присвоить переменной типа byte значение типа double. Java не сможет автоматически выполнить ваше желание. Не все числа типа double могут стать числом типа byte. Но часть чисел может, например, число 9. В таком случае используется так называемое приведение типов, чтобы подсказать Java о допустимости операции.

    Итак, автоматическое преобразование типов осуществляется, если оба типа совместимы и длина целевого типа больше длины исходного типа. В этом случае происходит преобразование с расширением. Вы всегда можете преобразовать любое число типа byte в число типа int. Такая операция произойдёт без вашего участия автоматически.

    Таблица выглядит следующим образом.

    Приведение типов

    Сплошные линии обозначают преобразования, выполняемые без потери данных. Штриховые линии говорят о том, что при преобразовании может произойти потеря точности.

    Типы целых чисел и чисел с плавающей точкой совместимы частично. Например, число 5 вполне может быть числом с плавающей точкой (5.0).

    Совсем не совместимы, например, char и boolean.

    С автоматическим приведением мы разобрались. Рассмотрим вариант, когда нужно преобразовать число типа int в число типа byte. Преобразование автоматически невозможно, поскольку byte меньше int. Но, например, число 99 вполне можно использовать и как int и как byte. В этом случае используется явное приведение типов, то есть преобразование из одного типа в другой (преобразование с сужением).

    Выглядит это следующим образом:

     int a; byte b; // какие-то операции с переменной b = (byte) a; 

    Как видите, вы в скобках указываете тип, к которому нужно явно привести переменную.

    Существует ещё вариант приведения с усечением. Это когда число с плавающей точкой приводится к целочисленному типу. В этом случае отбрасывается дробная часть (хвост). Например, число 3.14 будет усечено до числа 3:

     double a = 3.14; byte b = (byte) a; 

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

    Например, попробуйте преобразовать число 454.874 в тип byte:

     byte b; double d = 454.874; b = (byte) d; infoTextView.append("b равно " + b); 

    У меня вывелся удивительный результат: b равно -58.

    Рассмотрим такой пример. Допустим у нас есть выражение, где промежуточное значение может выходить за пределы допустимого диапазона:

     byte a = 44; byte b = 55; byte c = 101; int d = a * b - c; 

    При умножении переменных a * b промежуточный результат вышел за пределы диапазона допустимых значений для типов byte. Java во время вычисления промежуточных результатов автоматически повышает тип каждого операнда до int и ошибки не происходит.

    Это удобно, но может поставить в тупик в следующем примере:

     byte b = 50; b = b * 2; 

    С виду всё правильно. Если не слишком больше число типа byte, а итоговый результат тоже не выходит за диапазон допустимых значений. Но Java не позволит вам написать подобный код. Происходит следующее. Во время вычисления выражения тип операндов был автоматически повышен до int, как об этом говорилось выше. При этом тип результата тоже был повышен до int. Получается, что результат вычисления равен типу int, а мы пытаемся его присвоить переменной b, которая у нас объявлена как byte. И это несмотря на то, что итоговый результат может быть типом byte. Как же выйти из этого положения? Следует использовать явное приведение типов:

     byte b = 50; b = (byte) (b * 2); 

    Мы рассмотрели единичные примеры. Пора обобщить и запомнить несколько правил.

    Типы всех значений byte, short, char повышаются до типа int, как это было рассмотрено выше.

    Если один операнд имеет тип long, то тип всего выражения повышается до long.

    Если один операнд имеет тип float, то тип всего выражения повышается до float.

    Если один операнд имеет тип double, то тип всего выражения повышается до double.

     byte b = 45; char c = 'c'; short s = 1005; int i = 700000; float f = 4.55f; double d = 1.456; double result = (f * b) + (i / c) - (d * s); mInfoTextView.append("d равно " + d); 

    В первом промежуточном выражении (f * b) тип переменной b повышается до float и промежуточный результат также становится float. В следующем выражении (i / c) тип у переменной c повышается до int и промежуточный результат также становится типом int. В выражении (d * s) тип переменной s повышается до double и промежуточное выражение также становится double. В результате у нас появились три промежуточные значения типов: float, int, double. При сложении float и int мы получаем float, затем при вычитании с использованием float и double тип повышается до double, который и становится окончательным типом результата выражения.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *