Вы находитесь на странице: 1из 34

1

Java Foundations
3-4
Взаимная конвертация типов данных

© 2020, Корпорация Oracle и аффилированные с ней лица. Все права защищены.

2
Цели
• В данном уроке рассматриваются следующие темы:
−Преимущества автоматического повышения
• И когда следует быть осторожнее с повышением
−Преобразование переменных в другие типы данных
• И когда следует быть осторожнее с преобразованием
−Синтаксический анализ строк как числовых значений

JFo 3-4
Взаимная конвертация типов данных © 2020, Корпорация Oracle и аффилированные с ней лица. Все права защищены. 3

3
Темы
• Повышение
• Преобразование типов
• Синтаксический анализ строк

Взаимная Ввод
Общие Типы Типы данных с
конвертаци
сведения о числовы текстовы клавиату
я типов
переменных х данных х данных ры
данных

JFo 3-4
Взаимная конвертация типов данных © 2020, Корпорация Oracle и аффилированные с ней лица. Все права защищены. 4

4
Поздравляем!
• Вы успешно дошли до этого раздела курса!
• Вас ожидает повышение!

• Ваше повышение:
32 64
бита бита

JFo 3-4
Взаимная конвертация типов данных © 2020, Корпорация Oracle и аффилированные с ней лица. Все права защищены. 5

5
Ошибка при использовании double
• Что мы наблюдали ранее:
double x = 9/2; //Должно быть 4.5
System.out.println(x); //выводит 4.0
−Java вычисляет выражение, усекает значение до .5, а
затем возвращает ответ в double
• Если упростить этот сценарий, получится
следующее:
double x = 4;
System.out.println(x); //выводит 4.0
−Мы присвоили целочисленное значение переменной
double
−Java повышает это целочисленное значение до double
32 bits 64 bits
JFo 3-4
Взаимная конвертация типов данных © 2020, Корпорация Oracle и аффилированные с ней лица. Все права защищены. 6

6
Повышение
• Автоматическое повышение:
−Если присвоить более мелкий тип более крупному типу:

byte short int long

−Если присвоить интегральное значение типу с плавающей


точкой:
4 4,0

• Примеры автоматического повышения:


−long intToLong = 6;
−double intToDouble = 4;

JFo 3-4
Взаимная конвертация типов данных © 2020, Корпорация Oracle и аффилированные с ней лица. Все права защищены. 7

В некоторых случаях компилятор меняет тип переменной на тип, поддерживающий более


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

7
Почему повышение работает?
long
int
short
byte

• Тип byte может принимать значения от -128 до 127


• Все возможные значения byte можно уместить в тип
short
• Все возможные значения short можно уместить в тип int
• Все возможные значения int можно уместить в тип long
• Все возможные значения int можно уместить в тип
double без потери точности

JFo 3-4
Взаимная конвертация типов данных © 2020, Корпорация Oracle и аффилированные с ней лица. Все права защищены. 8

8
Опасности повышения, Пример 1
• Уравнение: 55555* 66666 = 3703629630
• Пример возможной проблемы:
int num1 = 55555;
int num2 = 66666;
long num3;
num3 = num1 * num2;

−Пример возможного решения:


int num1 = 55555;
long num2 = 66666; Изменение int на long
long num3;
num3 = num1 * num2;

JFo 3-4
Взаимная конвертация типов данных © 2020, Корпорация Oracle и аффилированные с ней лица. Все права защищены. 9

Перед назначением для переменной результат уравнения помещается во временное


расположение в памяти. Размер расположения всегда равен размеру типа int или
размеру самого большого типа данных, используемого в выражении или операторе.
Например, если в уравнении умножаются два типа int, размер контейнера будет равен
размеру типа int и составит 32 бита.
Иногда в результате умножения двух значений получается значение, выходящее за
пределы области int (например, 55555 * 66666 = 3,703,629,630 — это значение слишком
большое и не поддерживается типом int). В этом случае значение int усекается, чтобы
результат поместился во временное расположение в памяти. Этот расчет в итоге дает
некорректный ответ, поскольку переменная для ответа получает усеченное значение
(независимо от типа используемой переменной). Чтобы решить эту проблему, задайте
хотя бы для одной переменной в уравнении тип long. Это обеспечит максимально
возможный размер временного контейнера.

9
Опасности повышения, Пример 2
• Уравнение: 7 / 2 = 3.5
• Пример возможной проблемы:
int num1 = 7;
int num2 = 2;
double num3;
num3 = num1 / num2; //значение num3 3.0

• Пример возможного решения:


int num1 = 7;
double num2 = 2; Изменение int на double
double num3;
num3 = num1 / num2; //значение num3 3.5

JFo 3-4
Взаимная конвертация типов данных © 2020, Корпорация Oracle и аффилированные с ней лица. Все права защищены. 10

Деление
Такая же целочисленных
проблема возникает
значений
с другими
можеттипами
привести
данных.
к неточностям
Перед назначением
в десятичных
дляразрядах.
переменной результат уравнения помещается во временное расположение в памяти.
Размер расположения всегда равен размеру самого большого типа данных,
используемого в выражении или операторе. Например, если в уравнении делятся два
типа int, размер контейнера будет равен размеру типа int и составит 32 бита.

10
Темы
• Повышение
• Преобразование типов
• Синтаксический анализ строк

Взаимная Ввод
Общие Типы Типы данных с
конвертаци
сведения о числовы текстовы клавиату
я типов
переменных х данных х данных ры
данных

JFo 3-4
Взаимная конвертация типов данных © 2020, Корпорация Oracle и аффилированные с ней лица. Все права защищены. 11

11
Преобразование типов
• Когда применяется преобразование:
−Если более крупный тип присваивается более мелкому
типу:
byte short int long

−Если тип с плавающей точкой присваивается


интегральному типу:
3 3,0

• Примеры преобразования:
−int longToInt = (int)20L;
−short doubleToShort = (short)3.0;

JFo 3-4
Взаимная конвертация типов данных © 2020, Корпорация Oracle и аффилированные с ней лица. Все права защищены. 12

Преобразование типа уменьшает диапазон значений, буквально "обрезая" их до


меньшего размера. При этом меняется тип значения (например, значение long
преобразуется в значение int). После этого можно использовать методы, которые
принимают только определенные типы в качестве аргументов. В таких случаях можно
присвоить значения переменной с более мелким типом данных или сэкономить память.
Синтаксис для преобразования типа значения: identifier = (target_type) value.
Элементы синтаксиса:
identifier — имя, которое присваивается переменной.
value — значение, которое необходимо присвоить переменной identifier.
(target_type) — тип, в который будет преобразовано значение. Обратите внимание,
что элемент target_type должен быть заключен в круглые скобки.

12
Опасности преобразования типов
• Будьте внимательны, так как возможна потеря
точности
• Пример возможной проблемы:
int myInt;
double myPercent = 51.9;
myInt = (int)myPrecent; // Число "обрезано"
// myInt равно 51

JFo 3-4
Взаимная конвертация типов данных © 2020, Корпорация Oracle и аффилированные с ней лица. Все права защищены. 13

Когда значение float или double с дробной частью преобразуется в интегральный тип,
например int, все десятичные значения будут потеряны. Тем не менее, этот метод
преобразования типов бывает полезен, когда нужно усечь значение до целого числа
(например, 51,9 превращается в 51).

13
Опасности преобразования типов
• Пример возможной проблемы:
int myInt;
long myLong = 123987654321L;
myInt = (int)myLong; // Число "обрезано"
// myInt равно-566397263

• Пример более надежного преобразования:


int myInt;
long myLong = 99L;
myInt = (int)myLong; // Нет потери данных, только нули.
// myInt равно 99

JFo 3-4
Взаимная конвертация типов данных © 2020, Корпорация Oracle и аффилированные с ней лица. Все права защищены. 14

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

14
Обрезка интегрального значения
• Приведенные ранее примеры вызывают ряд
вопросов:
−Что означает "обрезка" интегрального значения?
−Почему мы получаем отрицательные значения?
• Настало время для очередного расследования …
−Преобразование
−Математика

JFo 3-4
Взаимная конвертация типов данных © 2020, Корпорация Oracle и аффилированные с ней лица. Все права защищены. 15

15
Упражнение 1
• Импортируйте и откройте проект Casting01
• Объявите и инициализируйте переменную byte со
значением 128:
− Изучите предупреждение NetBeans
− Закомментируйте эту проблемную строку
• Объявите и инициализируйте переменную short со
значением 128:
− Создайте оператор вывода, преобразующий short в byte
• Объявите и инициализируйте переменную byte со
значением 127
− Прибавьте 1 к этой переменной и выведите ее
− Снова прибавьте 1 к этой переменной и выведите ее

JFo 3-4
Взаимная конвертация типов данных © 2020, Корпорация Oracle и аффилированные с ней лица. Все права защищены. 16

16
Результаты исследования
• Переменная byte может принимать значения
от -128 до 127
− 128 —первое положительное значение, которое может
содержаться в short, но не в byte
− Попытка преобразовать переменную со значением 128 в
переменную byte равнозначна попытке присвоить
переменной byte значение 127 и применить инкремент +1
• При попытке инкрементировать переменную сверх ее
максимального значения переменная принимает
минимальное значение
− Пространство значений переменной зацикливается
− Когда это происходит, говорят о переполнении переменной
• 127 в двоичном формате выглядит как 01111111, а 128 в
двоичном формате — как 10000000
− Java использует первый бит числа для указания знака (+/-)

JFo 3-4
Взаимная конвертация типов данных © 2020, Корпорация Oracle и аффилированные с ней лица. Все права защищены. 17

Учитывайте эти дополнительные сведения. Чтобы решить набор задач, не обязательно


помнить эти факты. Важнее понять, как выполняется повышение и преобразование.

17
Допущения компилятора для интегрального типа
данных и типа с плавающей точкой
• Большинство операций дает результат int или
long
−Значения byte, short и char автоматически
повышаются до int перед выполнением операции
−Если выражение содержит значение long, все
выражение повышается до long
• Если выражение содержит число с плавающей
точкой, то все выражение повышается до
плавающей точки
• Все литеральные значения с плавающей точкой
рассматриваются как double

JFo 3-4
Взаимная конвертация типов данных © 2020, Корпорация Oracle и аффилированные с ней лица. Все права защищены. 18

Компилятор Java делает определенные допущения при вычислении выражений. Эти


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

18
Варианты устранения проблем
• Пример потенциальной проблемы:
int num1 = 53; // 32 бита памяти для хранения значения
int num2 = 47; // 32 бита памяти для хранения значения
byte num3; // 8 бит зарезервированной памяти
num3 = (num1 + num2); // вызывает ошибку компилятора

• Переменная byte должна поддерживать значение


100
• Однако Java отказывается присваивать это значение
и выдает ошибку "возможна потеря точности"
• Java допускает, что добавление переменных int
приведет к появлению значения, выходящего за
пределы пространства, выделенного для byte
JFo 3-4
Взаимная конвертация типов данных © 2020, Корпорация Oracle и аффилированные с ней лица. Все права защищены. 19

19
Варианты исправление проблем
• Решение с более крупным типом данных:
int num1 = 53;
int num2 = 47;
int num3; Изменение byte на int
num3 = (num1 + num2);

• Решение с преобразованием:
int num1 = 53; // 32 бита памяти для хранения значения
int num2 = 47; // 32 бита памяти для хранения значения
byte num3; // 8 бит зарезервированной памяти
num3 = (byte)(num1 + num2); // нет потери данных

JFo 3-4
Взаимная конвертация типов данных © 2020, Корпорация Oracle и аффилированные с ней лица. Все права защищены. 20

Чтобы устранить ошибку "возможна потеря данных", можно а) объявить переменную


слева (num3) как более крупный тип данных по сравнению с int; б) преобразовать тип
данных справа, чтобы он соответствовал типу данных слева.

20
Автоматическое повышение
• Пример возможной проблемы:
short a, b, c;
a = 1 ;
a и b автоматически повышаются до типа integer
b = 2 ;
c = a + b ; //ошибка компилятора

• Пример возможных решений:


−Задайте для переменной тип int в исходном объявлении:
− int c;
−Преобразуйте результат (a+b) в строке присвоения:
− c = (short)(a+b);

JFo 3-4
Взаимная конвертация типов данных © 2020, Корпорация Oracle и аффилированные с ней лица. Все права защищены. 21

В примере на этом слайде возникла ошибка, поскольку только два из трех операндов (a и
b) типа short автоматически повышаются до типа int перед добавлением.
В последней строке значения a и b преобразуются в типы int, и преобразованные
значения добавляются для получения результата int. Затем оператор присвоения (=)
пытается присвоить результат int переменной short (c). Однако такое присвоение
считается недопустимым и вызывает ошибку компилятора.

21
Использование типа Long
Использование символа L для
public class Person {
указания типа long приводит к
тому, что компилятор
распознает весь результат как
public static void main(String[] args){
long
int ageYears = 32;
int ageDays = ageYears * 365;
long ageSeconds = ageYears * 365 * 24L * 60 * 60;

System.out.println("Ваш возраст составляет"


+ ageDays + " дн.");
System.out.println("Ваш возраст составляет"
+ ageSeconds + " сек.");

}//конец метода main


}//конец класса Person

JFo 3-4
Взаимная конвертация типов данных © 2020, Корпорация Oracle и аффилированные с ней лица. Все права защищены. 22

В этом примере кода, который вычисляет возраст человека в днях и секундах,


используются принципы из данного раздела. Поскольку переменная ageSeconds
объявлена как long, одно из литеральных значений, используемое в операндах
присвоенного выражения, должно быть инициализировано как значение long (‘L’),
чтобы компилятор распознал это присвоение как допустимое.

22
Использование плавающих точек
• Пример возможной проблемы:
int num1 = 1 + 2 + 3 + 4.0; //ошибка компилятора
int num2 = (1 + 2 + 3 + 4) * 1.0; //ошибка компилятора
Выражения автоматически
повышаются до типа с
• Пример возможных решений: плавающей точкой
−Объявите num1 и num2 как тип double:
double num1 = 1 + 2 + 3 + 4.0; //10.0
double num2 = (1 + 2 + 3 + 4) * 1.0; //10.0

−Преобразуйте num1 и num2 в тип int в строке присвоения:


int num1 = (int)(1 + 2 + 3 + 4.0); //10
int num2 = (int)((1 + 2 + 3 + 4) * 1.0); //10

JFo 3-4
Взаимная конвертация типов данных © 2020, Корпорация Oracle и аффилированные с ней лица. Все права защищены. 23

Если выражение содержит число с плавающей точкой, то все выражение повышается до


плавающей точки.

23
Типы с плавающей точкой и присвоение
• Пример возможной проблемы:
float float1 = 27.9; //ошибка компилятора

• Пример возможных решений:


−Символ F сообщает компилятору о том, что 27,9 является
значением float:
float float1 = 27.9F;

−27.9 преобразуется в тип float:


float float1 = (float) 27.9;

JFo 3-4
Взаимная конвертация типов данных © 2020, Корпорация Oracle и аффилированные с ней лица. Все права защищены. 24

Точно так же, как интегральные типы при определенных обстоятельствах по умолчанию
рассматриваются как тип int, типы с плавающие точкой всегда по умолчанию
рассматриваются как double, если значение специально не объявлено как тип float.
Для этого необходимо поместить прописную букву F после числового значения. В
противном случае значение 27,9 расценивается как тип double и возникает ошибка
компилятора, поскольку значение типа double не входит в пространство значений
переменной float.

24
Упражнение 2
• Импортируйте и откройте проект Casting02
• В этой программе есть несколько ошибок
• Эти ошибки можно устранить, применив
следующие знания …
−Знание типов данных
−Знание принципа повышения
−Знание принципа преобразования

JFo 3-4
Взаимная конвертация типов данных © 2020, Корпорация Oracle и аффилированные с ней лица. Все права защищены. 25

25
Нижнее подчеркивание
• Вероятно, вы заметили нижние подчеркивания (_):
−Начиная с Java SE7, можно добавлять нижние
подчеркивания при присвоении числовых значений
−Нижние подчеркивания упрощают чтение больших чисел
−Нижние подчеркивания не влияют на значение
переменной
• Следующие два оператора эквивалентны:
int x = 123_456_789;

int x = 123456789;

JFo 3-4
Взаимная конвертация типов данных © 2020, Корпорация Oracle и аффилированные с ней лица. Все права защищены. 26

26
Темы
• Повышение
• Преобразование типов
• Синтаксический анализ строк

Взаимная Ввод
Общие Типы Типы данных с
конвертаци
сведения о числовы текстовы клавиату
я типов
переменных х данных х данных ры
данных

JFo 3-4
Взаимная конвертация типов данных © 2020, Корпорация Oracle и аффилированные с ней лица. Все права защищены. 27

27
Преобразование строк в числовые данные
• Когда программа предлагает пользователю ввести
данные в диалоговом окне …
−Пользователь может ввести любой текст
−Этот текст проще всего представить в виде объекта String
• Но иногда требуется выполнить математические
операции с данными, введенными пользователем
−Если вы разрабатываете программу, которая
поддерживает ввод текстовых
данных, может потребоваться
преобразовать объект String в
числовые типы данных

JFo 3-4
Взаимная конвертация типов данных © 2020, Корпорация Oracle и аффилированные с ней лица. Все права защищены. 28

28
Синтаксический анализ строк
• Преобразование текста в числовые данные — одна
из форм синтаксического анализа
• Преобразование String в int:
int intVar1 = Integer.parseInt("100");

• Преобразование String в double:


double doubleVar2 = Double.parseDouble("2.72");

JFo 3-4
Взаимная конвертация типов данных © 2020, Корпорация Oracle и аффилированные с ней лица. Все права защищены. 29

29
Упражнение 3, Часть 1
• Импортируйте и откройте проект Parsing01
• Объявите и инициализируйте 3 объекта String со
следующими данными:
Строковая переменная Описание Примеры значений
shirtPrice Текст, преобразуемый в int: "15"
taxRate Текст, преобразуемый в "0,05"
double:
gibberish Бессмысленный набор "887ds7nds87dsfs"
данных

JFo 3-4
Взаимная конвертация типов данных © 2020, Корпорация Oracle и аффилированные с ней лица. Все права защищены. 30

30
Упражнение 3, Часть 2
• Выполните синтаксический анализ и умножьте
shirtPrice*taxRate, чтобы получить значение налога
−Выведите это значение
• Попробуйте проанализировать taxRate как int
−Прочтите сообщение об ошибке
• Попробуйте проанализировать gibberish как int
−Прочтите сообщение об ошибке

JFo 3-4
Взаимная конвертация типов данных © 2020, Корпорация Oracle и аффилированные с ней лица. Все права защищены. 31

31
Проблема с данными,
введенными пользователем
• Эта ошибкNumberFormatException
− а возникает потому, что невозможно выполнить
синтаксический анализ значения
− Если пользователь может ввести любые данные, создается
риск
int intVar1 = Integer.parseInt("Щенки!");

• В программе не должны возникать серьезные сбои из-


за данных, введенных пользователем
− Но это обстоятельство пока можно игнорировать
− Сначала нужно выяснить, как получить данные, введенные
пользователем
− Этому будет посвящен следующий урок
− В Разделе 8 вы узнаете, как обрабатывать ошибки и
исключения

JFo 3-4
Взаимная конвертация типов данных © 2020, Корпорация Oracle и аффилированные с ней лица. Все права защищены. 32

32
Сводка
• В этом уроке вы узнали следующее:
−Преимущества автоматического повышения
• И когда следует быть осторожнее с повышением
−Преобразование переменных в другие типы данных
• И когда следует быть осторожнее с преобразованием
−Синтаксический анализ строк как числовых значений

JFo 3-4
Взаимная конвертация типов данных © 2020, Корпорация Oracle и аффилированные с ней лица. Все права защищены. 33

33
34