Лабораторная работа 1 2 лабораторная работа 2 31 лабораторная работа 3 44 лабораторная работа 4 74
Скачать 1.76 Mb.
|
ЛАБОРАТОРНАЯ РАБОТА №2Тема: Преобразование и приведение типов. Компиляция программ на языке Java. Чтение консольного ввода. Математические операции. Цель: Приобрести практические навыки разработки программных средств на языке java с использованием ввода данных и математических операций. Теоретические сведения Рассматриваемые вопросы: 2.1 Преобразование и приведение типов 2.2 Приведение несовместимых типов 2.3 Автоматическое расширение типа в выражениях 2.4 Компиляция программы 2.5 Чтение консольного ввода 2.6 Чтение символов 2.7 Математические операции 2.1 Преобразование и приведение типов При написании программы бывают ситуации, когда присваиваются значения одного типа переменной другого типа. Если два типа совместимы, то Java выполнит преобразование автоматически. Например, всегда возможно назначить int-значение long-переменной. Однако не все типы совместимы и, таким образом, не все преобразования типов неявно позволены. Например, не определено никакого преобразования из double в byte. К счастью, все еще возможно осуществить преобразование между несовместимыми типами. Чтобы это сделать, следует использовать специальную операцию приведения типов(cast), которая выполняет явное преобразование между несовместимыми типами. Автоматическое преобразование типов в Java Когда один тип данных назначается переменной другого типа, будет иметь место автоматическое преобразование типов, если выполняются два следующих условия: - два типа совместимы; - целевой тип больше чем исходный. Когда эти два условия выполняются, имеет место расширяющее преобразование (widening conversion). Например, тип int всегда достаточно большой, чтобы содержать все допустимые byte-значения, так что никакой явный оператор приведения не требуется. Для расширяющих преобразований числовые типы, включая целый и с плавающей точкой, являются совместимыми друг с другом. Однако числовые типы не совместимы с char или boolean. Типы char и boolean не совместимы также и друг с другом. Java выполняет автоматическое преобразование типов при сохранении литеральной целочисленной константы в переменных типа byte, short или long. 2.2 Приведение несовместимых типов Хотя автоматическое преобразование типов полезно, оно не удовлетворяет всем потребностям. Например, как быть, если нужно назначить int-значение byte-переменной? Это преобразование не будет выполнено автоматически, потому что тип byte меньше, чем int. Данный вид преобразования иногда называется сужающим преобразованием(narrowing conversion), т. к. вы явно делаете значение более узким, чтобы оно вписалось в целевой тип. Чтобы создавать преобразование между двумя несовместимыми типами, нужно использовать приведение типов. Приведение(cast) — это и есть явное преобразование типов. Оно имеет общий формат: (target-type) value Здесь target-typeопределяет желаемый тип, к которому следует преобразовать указанное value. Например, следующий фрагмент приводит int к byte. Если целое значение больше, чем диапазон byte-типа (256), то оно будет редуцировано по модулю этого диапазона (до остатка от целочисленного деления этого значения на 256). int а; byte b; // ... b = (byte) a; Другой тип преобразований — усечение(trancation), произойдет, когда значение с плавающей точкой назначается целому типу. Целые числа не имеют дробных частей. Таким, образом, когда значение с плавающей точкой назначается целому типу, дробная часть теряется. Например, если значение 1.23 назначается целой переменной, результирующее значение будет просто 1, а 0.23 будет усечено. Конечно, если числовое значение слишком велико, чтобы вписаться в целевой целый тип, то оно будет редуцировано по модулю диапазона целевого типа. Следующая программа демонстрирует некоторые преобразования типов, которые требуют приведений: // Демонстрирует приведения типов class Conversion { public static void main(String args[]) { byte b; int i = 257; double d = 323.142; System.out.println("Приведение int к byte"); b = (byte) i; System.out.println("i и b " + i + " " + b); System.out.println("Приведение double Kint."); i = (int) d; System.out.println("d и i " + d + " " + i); System.out.println("Приведение double к byte."); b = (byte) d; System.out.println("d and b " + d + " " + b); } } Эта программа генерирует следующий вывод: Приведение int к byte i и b 257 1 Приведение double к int d и i 323.142 323 Приведение double к byte d и b 323.142 67 Посмотрим на каждое преобразование. Когда значение 257 приводится к byte-переменной, результат — остаток от деления 257 на 256 (диапазон типа byte) в этом случае равен 1. Когда d преобразуется к int, его дробный компонент теряется. Когда d преобразуется к byte, его дробный компонент теряется, и значение редуцируется по модулю 256, что в этом случае дает 67. 2.3 Автоматическое расширение типа в выражениях В дополнение к операции назначения (присваивания) в выражениях есть и другое место, где могут происходить некоторые преобразования типов — в выражениях.Чтобы увидеть, как и почему это происходит, приведем следующие соображения. В выражении точность, требуемая от промежуточного значения, будет иногда превышать диапазон любого операнда. Например, рассмотрим следующие выражения: byte а = 40; byte b = 50; byte с = 100; int d = а * b / с; Результат промежуточного выражения а*b превышает диапазон любого из его byte-операндов. Чтобы управлять проблемой этого рода, Java при оценке выражения автоматически расширяет (повышает) тип каждого byte или short операнда до int. Это означает, что подвыражение а*b вычисляется с использованием целых чисел — не байтов. Таким образом, результат 2000 промежуточного выражения 50*40 является законным даже при том, что оба операнда (а и b) определены с типом byte. Не смотря на свою полезность, автоматические расширения типов могут вызывать плохо распознаваемые ошибки во время компиляции. Например, этот, казалось бы, корректный код порождает проблему: byte b = 50; b = b * 2; // Ошибка! Невозможно назначить int-значение byte-переменной! Во второй строке кода происходит попытка сохранить совершенно правильное byte-значение (50*2) в byte-переменной b. Однако, из-за того что операнды были автоматически расширены до типа int (во время оценки выражения), результат также был расширен до int. Таким образом, результат выражения имеет теперь тип int, который не может быть назначен byte-переменной без использования приведения. В таком случае следует использовать явное приведение типа: byte b = 50; b = (byte)(b*2) ; что выдает правильное значение 100. 2.4 Компиляция программы Чтобы скомпилировать проrpамму, нужно запустить компилятор (javac), указав имя исходноro файла в командной строке, например: C:\>javac Example.java Компилятор javac создаст файл Example.class, содержащий байткодовую версию программы. Байткод Java это промежуточное представление программы, содержащее инструкции, которые будет выполнять виртуальная машина java. Следовательно, результат работы компилятора javac не является непосредственно исполняемым кодом. Чтобы действительно выполнить программу, необходимо воспользоваться программой запуска приложений java, которая носит имя java. При этом ей потребуется передать имя класса Example в качестве аpгументa командной строки, как показано в следующем примере: C:\>java Example В процессе компиляции исходного кода каждый отдельный класс помещается в собственный выходной файл, названный по имени класса и получающий расширение .class. Именно поэтому исходным файлам jаvа целесообразно присваивать имена, совпадающие с именами классов, которые они содержат имя исходного файла будет совпадать с именем файла с расширением .class. При запуске java описанным способом в командной строке в действительности указывают имя класса, который нужно выполнить. Программа будет автоматически искать файл с указанным именем и расширением .class. Если прогpaммa найдет файл, она выполнит код, содержащийся в указанном классе. 2.5 Чтение консольного ввода В java1.0 единственным способом выполнения консольного ввода было использование байтового потока, и существует большой объем cтapoгo кода, в котором применяется этот подход. Сегодня применение байтового потока для чтения консольного ввода по прежнему технически возможно, но поступать так не рекомендуется. Предпочтительный метод чтения консольного ввода это использовать символ-ориентированный поток, что значительно упрощает возможности интернационализации и поддержки разрабатываемых программ. В java консольный ввод выполняется чтением System.in. Чтобы получить символьный поток, присоединенный к консоли, вы должны поместить System.in в оболочку объекта BufferedReader. BufferedReader поддерживает буферизованный входной поток. Наиболее часто используемый eгo конструктор выглядит так: BufferedReader(Reader iпputReader) Здесь inputReader это поток, который связывается с создаваемым экземпляром BufferedReader.Reader абстрактный класс. Одним из его конкретных наследников является InputStreamReader, который преобразует байты в символы. Для получения объекта InputStreamReader, который присоединен к System.in, служит следующий конструктор: InputStreamReader(InputStream iпputStream) Поскольку System.in ссылается на объект типа InputStream, он должен быть использован как параметр iпputStream. Собрав все вместе, получим следующую строку кода, которая создает BufferedReader, соединенный с клавиатурой: BufferedReader br = new BufferedReader(newInputStreamReader(System.in)); После выполнения этого оператора br представляет собой основанный на символах поток, подключенный к консоли через System.in. 2.6 Чтение символов Для чтения символа из BufferedReader применяется read(). Ниже показана версия read(), которая будет использоваться: int read() throws IOException Каждый раз, когда вызывается метод read(), он читает символ из входного потока и возвращает eгo как целое значение. При достижении конца потока возвращается l. Как видите, метод может возбудить исключение IOException. В следующей программе демонстрируется применение read(), читая символы с консоли до тех пор, пока не пользователь не введет "q". Обратите внимание, что любые исключения ввода/вывода, которые могут быть сгенерированы, просто передаются в main ( ). Такой подход распространен при чтении с консоли, но при желании вы можете обработать ошибки такого рода самостоятельно. // Использование BufferedReader для чтения символов с консоли. import java.io.*; class BRRead { public static void main(String args[]) throws IOException { char с; BufferedReader br = new BufferedReader(newInputStreamReader(System.in)); Sustеm.оut.рrintln("Вводите символы, 'q' для выхода."); // читать символы do { с (char) br.read(); System.out.println(c); while(c ! 'q'); } } Ниже показан пример запуска этой прогpаммы: Вводите символы, 'q' для выхода. 12сq 1 2 с q 2.7 Математические операции Класс Маth содержит все функции с плавающей точкой, которые используются в гeoметрии и тригонометрии, а также некоторые методы общего назначения. В Маth определены две константы double: Е (равную приблизительно 2,72) и РI (равную примерно 3,14). Методы, перечисленные в табл. 1, принимают параметр типа double, выражающий угол в радианах и возвращающий результат соответствующей трансцендентной функции. Табл.1
Методы, перечисленные в табл. 2, принимают в качестве параметра результат трансцендентной функции и возвращают угол в радианах, который порождает такой результат. Они представляют собой инверсию соответствующих функций из предыдущей таблицы. Табл. 2
В классе Math определен набор экспоненциальных методов, которые описаны в табл. 3. Табл. 3.
В классе Math определены некоторые методы, которые предназначены для выполнения различного рода операций округления. Они перечислены в табл. 4. Обратите внимание на два метода ulp () в конце таблицы. В данном контексте "ulp" означает "units in the last place" (единицы на последнем месте). Это указывает число единиц между значением и ближайшим большим значением. Это можно использовать для получения точности результата. Табл. 4
В дополнение к методам, приведенным в таблицах выше, в Math определено еще несколько методов, которые перечислены в табл. 5. Табл. 5
В следующей программе демонстрируется использование toRadians() и toDegrees(). // Демонстрация применения toDegrees() и toRadians(). class Angles { public static void main(String args[]) { double theta = 120.0; System.out.println(theta + " градусов равно " +Math.toRadians(theta) + " радиан."); theta = 1.312; System.out.println(theta + " радиан равно " +Math.toDegrees(theta) + " градусов."); Вывод этой программы показан ниже: 120.0' градусов равно 2.0943951023931953 радиан. 1.312 радиан равно 75.17206272116401 радиан. Индивидуальные задания Написать программу на java для вычисления выражения, используя консольный ввод/вывод: y= ; y= ; y= ; y= ; y= ; y= ; y= ; y= ; y= ; y= ; y= ; y= ; y= ; y= ; y= ; y= ; y= ; y= ; y= ; y= . Контрольные вопросы При каких условиях выполняется автоматическое преобразование типов? Для чего нужно приведение типов? Приведите пример программы автоматического расширения типов с пояснением. Почему исходным файлам jаvа целесообразно присваивать имена, совпадающие с именами классов? Приведите пример программы чтения символов с консоли. Какие экспоненциальные методы определены в классе Math? Какие методы определены в классе Math для округления? Какие методы определены в классе Math для перевода из градусов в радианы и из радиан в градусы? Приведите пример. Рекомендуемая литература Основная литература Шилдт Г., Ноутон П. Java 2. Наиболее полное руководство, 2001. Павловская Т.А., Щупак Ю.А. C++. Объектно-ориентированное программирование. Практикум. СПб. Питер, 2006. Г.Шилдт. Полный справочник по Java SE6 2007. Б.Эккель. Философия Java (4е издание), 2009. К. Арнольд, Д. Гослинг. Язык программирования Java. Питер Пресс, Санкт-Петербург, 1997. Дополнительная литература М. Эферган Java: справочник .- QUE Corporation, 1997, Издательство "Питер Ком", 1998 Д. Вебер Технология Java в подлиннике .- QUE Corporation, 1996, "BHV-Санкт-Петербург",1997. Н. Бартлетт, А. Лесли, С. Симкин Программирование на Java. Путеводитель .- The Coriolis Group,Inc.,1996, Издательство НИПФ "ДиаСофт Лтд.",1996 К. Джамса Библиотека программиста Java .- Jamsa Press, 1996, ООО "Попурри", 1996 К. Арнольд, Д. Гослинг Язык программирования Java .- Addison-Wesley Longman,U.S.A.,1996, Издательство "Питер-Пресс", 1997. |