3.1.4 Ввод и считывание данных
Переменным можно присваивать значения, введенные извне. Давайте немного отвлечемся от абстрактных рассуждений и запустим две простых программы, которые запрашивают данные у пользователя и обрабатывают их. К этому моменту вы должны уметь создавать проекты в среде NetBeans IDE, поэтому я привожу только исходный код примеров.
Программа из листинга 3.1 поддерживает консольный ввод пользователь читает запросы программы и вводит данные в окне системного монитора среды NetBeans. В программе из листинга 3.2 задействованы модальные окна с привычным графическим оформлением. Вы увидите, насколько просты эти программы. Не волнуйтесь, если что-то непонятно. Пока просто привыкайте к новым терминам. По мере чтения этой книги придет полное понимание.
Листинг 3.1 Чтение консольного ввода, вывод в консоль
import java.util.Scanner;
public class Listing3_1 {
public static void main (String [] args) {
// Создаем объект input класса Scanner
Scanner input = new Scanner(System.in);
// Переменная для хранения имени пользователя
String name;
// Переменная для хранения отчества пользователя
String surName;
// Переменная для хранения даты рождения пользователя
int yearBorn;
// Переменная для хранения текущего года
int yearNow;
// Выводим запрос данных
System.out.print («Ваше имя:»);
// Считываем имя (строка)
name = input.nextLine ();
System.out.print («Ваше отчество:»);
// Считываем отчество (строка)
surName = input.nextLine ();
System.out.print («Какой сейчас год?»);
// Считываем текущий год (целое число)
yearNow = input.nextInt ();
System.out.print («В каком году вы родились?»);
// Считываем год рождения (целое число)
yearBorn = input.nextInt ();
System.out.println («Здравствуйте, "+name+" "+surName+»!»);
System.out.println («Ваш возраст: "+ (yearNow-yearBorn) +».»);
}
}
В первой строке этой программы мы импортируем класс Scanner, который входит в состав системного пакета java. util. Затем мы создаем новый объект класса Scanner и назначаем ему идентификатор (имя) input. После этого приступаем к получению данных от пользователя. Выводим в консоль текстовый запрос и считываем ответ. Обратите внимание, что текстовые ответы мы считываем при помощи метода nextLine (), а целочисленные при помощи метода nextInt (). В противном случае возникнет ошибка несоответствия типа данных. Ведь мы объявили переменные yearNow и yearBorn как целые числа.
Отдельно разберем строку
System.out.println («Ваш возраст: "+ (yearNow-yearBorn) +».»);
В этой строке происходит арифметическое вычисление возраста пользователя, формирование строки вывода и вывод в консоль. Выражение (yearNow-yearBorn) обязательно должно быть в круглых скобках, потому что сначала должно быть вычислено его значение, а затем результат вычисления будет преобразован из числа в строку (автоматическое приведение типов).
Наберите или скачайте исходный код программы и запустите проект на выполнение. Введите ответы на вопросы. В окно терминала должно быть выведено что-то наподобие этого:
run:
Ваше имя: Иван
Ваше отчество: Петрович
Какой сейчас год? 2018
В каком году вы родились? 1988
Здравствуйте, Иван Петрович!
Ваш возраст: 30.
СБОРКА УСПЕШНО ЗАВЕРШЕНА (общее время: 22 секунды)
На компьютере с ОС Windows вместо символов кириллицы вы можете увидеть квадратики. В этом случае необходимо настроить кодировку проекта. В окне просмотра содержимого проекта щелкните правой кнопкой мыши на названии проекта и выберите пункт Свойства контекстного меню. В открывшемся окне найдите поле «Кодировка» и выберите в списке кодировку windows1251. Нажмите OK.
Вторая программа имеет графический интерфейс, основанный на модальных окнах. Это специальные окна, которые содержат сообщение или поле ввода. Чтобы программа продолжила выполнение, пользователь обязательно должен отреагировать на появление окна ввести данные или прочитать сообщение и закрыть.
Листинг 3.2 Ввод и вывод данных в модальных окнах
// импортируем класс JOptionPane из библиотеки Swing
import javax.swing.JOptionPane;
public class Listing3_2 {
public static void main (String [] args) {
// Объявление числовых переменных
int yearNow, yearBorn, userAge;
// Объявление строковой переменной
String userData;
// Выводим окно запроса текущей даты
userData = JOptionPane.showInputDialog («Какой сейчас год?»);
// Преобразуем строку в число в явном виде
yearNow = Integer.parseInt (userData);
// Выводим окно запроса года рождения
userData = JOptionPane.showInputDialog («В каком году вы родились?»);
import javax.swing.JOptionPane;
public class Listing3_2 {
public static void main (String [] args) {
// Объявление числовых переменных
int yearNow, yearBorn, userAge;
// Объявление строковой переменной
String userData;
// Выводим окно запроса текущей даты
userData = JOptionPane.showInputDialog («Какой сейчас год?»);
// Преобразуем строку в число в явном виде
yearNow = Integer.parseInt (userData);
// Выводим окно запроса года рождения
userData = JOptionPane.showInputDialog («В каком году вы родились?»);
// Преобразуем строку в число в явном виде
yearBorn = Integer.parseInt (userData);
// Вычисляем возраст
userAge = yearNow yearBorn;
// Выводим окно сообщения с результатом
JOptionPane.showMessageDialog (null, «Ваш возраст: " + userAge);
}
}
В первой строке программы мы импортируем класс JOptionPane из библиотеки Swing. Библиотека Swing содержит набор классов для разработки приложений с графическим интерфейсом. Это очень емкая и мощная библиотека, входящая в пакет поставки SDK. Вы будете постоянно использовать ее при разработке приложений с графическим интерфейсом. Класс JOptionPane предназначен для создания стандартных модальных (диалоговых) окон. Для вывода окна с запросом данных применяется метод showInputDialog (), а для вывода сообщения метод showMessageDialog ().
Любые значения, возвращаемые методом showInputDialog () являются строковыми данными. Чтобы выполнить над ними арифметические действия, необходимо в явном виде преобразовать строки в числа. Мы делаем это при помощи метода parseInt () системного класса Integer:
yearNow = Integer.parseInt (userData);
Программа завершается вычислением возраста пользователя и выводом результата.
Запустите проект на выполнение. Вы должны поочередно увидеть три диалоговых окна (рис. 3.1).
Рис.3.1 Диалоговые окна запроса и вывода данных
Если все работает правильно, нажмите клавишу F11 или выберите пункт меню Выполнить | Собрать проект. Будет создан исполняемый файл приложения. Его можно запустить на любом компьютере, где установлена Java-машина. Оформление окон приложения цветовая схема, форма кнопок может различаться в зависимости от операционной системы и реализации Java-машины.
По умолчанию файл проекта находится в папке Документы | NetBeansProjects. Внутри папки с именем проекта найдите папку dist. В этой папке находится готовый распространяемый файл приложения с расширением jar.
3.2 Приведение типов
Иногда возникает ситуация, когда в одном выражении присутствуют разные типы данных. Будем считать, что это осознанное действие, а не ошибка программиста, ибо такие ошибки чрезвычайно коварны. Несоответствие типов в выражении не всегда влечет за собой ошибку компиляции, но программа может вести себя не так, как ожидалось. Изменение типа данных в процессе выполнения программы называется приведением типа. Реализация приведения типов зависит от конкретного языка. Некоторые языки допускают большие вольности в приведении типов. За это их резко критикуют профессиональные программисты.
Про особенности приведения типов в разных языках программирования можно написать отдельную брошюру. Но в нашем вводном курсе мы ограничимся изложением основных принципов.
Приведение типов разделяется на явное (указанное программистом в коде) и неявное (автоматическое).
При явном приведении типов перед значением или выражением в скобках указывается новый тип, например:
double x = 15.7;
y = (int) 15.7;
В этом примере число с плавающей точкой приводится к типу «целое», при этом просто отбрасывается дробная часть. Результатом приведения будет усеченное значение 15, а не округленное 16.
Обратное преобразование из целого в число с плавающей точкой тоже выполняется, но это происходит автоматически. Запомните простое правило: если в выражении участвуют операнды разных типов, то результат приводится к тому типу, который занимает больше места в памяти. Поэтому важно, чтобы тип переменной, которой вы хотите присвоить результат вычислений, совпадал с типом результата. Вот простой пример приведения типов:
byte a = 2;
а = (byte) (a*5);
В этом примере целочисленный литерал 5 трактуется, как значение типа int, поэтому результат умножения будет расширен до типа int. Но переменная объявлена, как byte, поэтому возникнет конфликт выделения памяти и ошибка компиляции.
Чтобы избежать ошибки, мы в явном виде приводим результат умножения к типу byte. При этом из 32 байт остаются только младшие 8, а остальные отбрасываются. Это опасная потеря информации. Может получиться так, что при маленьких исходных значениях результат будет верным. Но стоит разрядности результата умножения превысить 8 битов, и после приведения типов вы получите неправильный результат вычислений. Такая блуждающая ошибка зависит от сочетания факторов и трудно поддается локализации в коде.