Лабораторна робота 4
Використання базових засобів мови Java
1 Завдання на лабораторну роботу
1.1 Індивідуальне завдання
Створити консольну програму, в якій здійснюється обчислення значень функції на певному інтервалі. У програмі треба визначити значення початку інтервалу, кінця інтервалу, а також величини кроку, з яким змінюється аргумент. Відповідні значення слід прочитати з клавіатури.
Безпосередньому створенню програми повинне передувати дослідження поведінки функції на різних інтервалах.
Програма повинна містити визначення та введення необхідних даних і один великий цикл, у тілі якого здійснюється
- обчислення функції різними способами, залежно від значення аргументу
- виведення на консоль аргументу та результату на кожному кроці циклу.
Програма повинна містити окрему статичну функцію для обчислення значення y залежно від значення аргументу x. Варіант функціональної залежності, який слід реалізувати у програмі, визначається відповідно до номеру студента у списку групи.
Таблиця 1.1 – Індивідуальні завдання
1.2 Степені числа 8
Увести значення n
(від 0 до 10) і вивести значення степенів числа 8 до n
включно. Реалізувати два підходи – з використанням арифметичних і побітових операцій.
1.3 Факторіали
Реалізувати алгоритм і програму, у якій уводиться n обчислюється і виводиться на екран n! (факторіал числа n). Реалізувати два способи – за допомогою циклу та за допомогою рекурсивної функції:
n! = 1 * 2 * ... * n.
2 Методичні вказівки
2.1 Основні особливості мови програмування Java і Java-платформи. Встановлення Java
Під Java розуміють:
- мову програмування;
- програмну платформу.
Робота над мовою Java почалася з 1990 р. Першою назвою мови був Oak. Назва Java з'явилася в 1995 р. Основними властивостями мови є такі:
- крос-платформна (синтаксис мови та набір стандартних засобів не залежить від певної операційної системи та типу комп'ютера);
- стандартизована;
- об'єктно-орієнтована;
- підтримує строгу типізацію (обмежена кількість примітивних типів, удосконалені правила перетворення типів);
- легка в освоєнні і розробці;
- забезпечує підвищену надійність завдяки відсутності вказівників та обов'язковій перевірці віртуальною машиною коду класів, що завантажуються, і дій, які виконує програма;
- пристосована до розробки Іінтернет-застосунків.
Для запобігання багатьох типових помилок, притаманних програмам на C++, запропоновано механізм автоматичного збирання сміття (garbage collection). Цей механізм автоматично підраховує кількість посилань на кожний об'єкт Java. Коли на об'єкт більше не вказує жодне посилання, він вважається непотрібним та може бути видалений з пам'яті, звільняючи ресурси для програми.
Синтаксис Java багато в чому схожий з C++. Разом з тим, Java має властивість крос-платформності (транспортабельності), застосовує інтерпретатор байт-коду, використовує іншу об'єктну модель (аналогічну C#), тобто іншу сукупність об'єктно-орієнтованих концепцій і набору засобів опису класів і зв'язків між ними, а також механізмів створення об'єктів, та ін.
На відміну від багатьох інших мов і систем програмування, вихідний код Java компілюється не безпосередньо в машинні команди, а в так званий байт-код. Набір команд цього коду повинен бути інтерпретований для виконання на конкретному комп'ютері під керуванням конкретної операційної системи. Іншими словами, потрібна спеціальна програмна платформа.
Програмна платформа у загальному випадку включає набір програмних засобів, що забезпечують виконання інших програм. Програмні засоби, що складають програмну платформу, як правило, мають стандартний набір функцій, технічно по-різному реалізованих на різних апаратних платформах і в різних операційних системах. Java-платформу складають віртуальна машина Java і стандартні класи.
Віртуальна машина Java (Java Virtual Machine) – це програма, яка інтерпретує і виконує байт-код, попередньо створений з вихідного тексту програми компілятором.
Крім мови Java, наведені нижче мови також створені для розробки Java-застосунків:
|
|
Крім того, низка раніше створених універсальних мов також забезпечує створення застосунків для JVM:
|
|
|
Кількість мов, орієнтованих на JVM дуже швидко розширюється. Продовжують створюватися нові мови з підтримкою JVM.
Концептуально платформа Java реалізована на різних рівнях, залежно від призначення програмних застосунків:
- Java Card – технологія, яка дозволяє безпечно запускати невеликі Java-програми (аплети) на смарт-картах та подібних пристроях малої пам’яті.
- Java ME (Micro Edition) – визначає кілька різних наборів бібліотек для пристроїв з обмеженими можливостями; її часто використовують для розробки додатків для мобільних пристроїв, КПК, телевізорів та принтерів.
- Java Platform, Standard Edition, (Java SE) – стандартна версія платформи Java, призначена для створення і виконання застосунків, розрахованих на індивідуальне користування;
- Java Platform, Enterprise Edition, скорочено Java EE – платформа, яка реалізує серверну архітектуру для задач середніх і великих підприємств.
Технічно платформа Java SE також реалізована на двох рівнях:
- Java Runtime Environment (JRE) – середовище виконання Java-програм. Фізично це набір програмних засобів, що включають віртуальну машину Java і бібліотеку класів.
- Java Development Kit (JDK) – комплект розробника застосунків мовою Java, що включає в себе компілятор Java (javac), стандартні бібліотеки класів Java, приклади, документацію, різні утиліти і середовище виконання Java-програм (JRE).
Кожна нова версія Java має нові можливості в порівнянні з попередньої. Java версії 1.2 настільки перевершувала платформу 1.1, що, починаючи з її, усі наступні версії назвали платформою Java 2. Починаючи з JDK 1.5 прийнято казати про Java 5. Версія Java 6 (JDK 1.6) відрізняється від попередньої переважно розширеними бібліотеками класів. Версії Java 7 і Java 8, окрім розширених бібліотек класів, надають велику кількість нових зручних синтаксичних конструкцій.
Починаючи з 2017 року версії Java додаються кожні півроку. На жаль, в версіях, починаючи з дев'ятої, не повністю реалізовано принцип зворотної сумісності. Код, створений у попередніх версіях Java, не може бути виконаний без додаткової переробки та перекомпіляції. Через ці проблеми Java 8 залишається розповсюдженою версією серед розроблювачів і далі підтримується компанією Oracle. Подальші приклади в тексті орієнтовані на використання Java 8.
Для того щоб Java-застосунок можна було виконати на конкретному комп'ютері, на ньому необхідно встановити JRE або JDK. Встановлення JRE достатнє в більшості випадків, якщо мова йде не про розробку, а тільки про запуск застосунків. Крім того, для роботи деяких інтегрованих середовищ, наприклад Eclipse, достатньо JRE, оскільки середовище може містити вбудований компілятор Java.
Якщо робота здійснюється під управлінням операційної системи Windows, встановлення здійснюється таким чином. З головної сторінки сайту java.com слід перейти за посиланням Download (Завантажити). На наступній сторінці слід погодитися з умовами ліцензійної угоди, натиснувши відповідну кнопку, після чого починається завантаження програми установки Java для автоматично визначеної операційної системи. У багатьох випадках варіант інсталяції слід вибирати вручну. Для цього використовується посилання See all Java downloads.
Перед встановленням JRE доцільно закрити браузери та інші програми, які можуть використовувати Java. Під час інсталяції можна змінити теку, в яку здійснюється встановлення (Change destination folder). Якщо на комп'ютері раніше були встановлені старі версії JRE. інсталятор запропонує їх видалити. Попередні версії можна вибрати зі списку. Зазвичай після інсталяції в браузері відкривається сторінка, яка дозволяє перевірити версію Java.
Після завершення можна перевірити успішність встановлення, набравши в командному рядку (Start | Run... cmd
) таку команду:
java -version
У консольному вікні буде виведена версія JRE.
2.2 Інтеґроване середовище Eclipse
2.2.1 Основні концепції
Eclipse – це універсальна платформа, яка створена для побудови інтеґрованих середовищ розробки (IDE).
Як інтеґроване середовище Eclipse може бути використаний у сполученні з C, C++ та іншими мовами. Але у переліку мов програмування Java посідає особливе місце. Зокрема, Eclipse розповсюджується з вбудованою підтримкою Java.
Інтеґроване середовище можна завантажити зі сторінки https://eclipse.org/downloads/ сайту Eclipse Foundation. У списку Developer Builds обираємо посилання Eclipse IDE for Java Developers і тип операційної системи. Після завантаження файлу eclipse.zip
вміст архіву треба розкрити на твердий диск. Eclipse не вимагає процедури інсталяції. Далі слід знайти і завантажити на виконання файл eclipse.exe
.
З кожним варіантом використання Eclipse пов'язана так звана перспектива. Перспективою, у термінології Eclipse, називається конфігурація платформи, що відповідає певній ролі. Функціональність, яка необхідна користувачеві, визначає набір і розташування вікон, меню, гарячих клавіш та інших елементів інтерфейсу для цієї перспективи. Приклади перспектив – Java, Debug, C++ та ін.
Під час першого завантаження Eclipse пропонується встановити так названий робочий простір (workspace). Робочий простір є контейнером для проектів. Крім того, в ньому містяться налаштування, що зберігаються компонентами Eclipse, а також допоміжні дані. Фізично робочий простір представлено текою, підкаталоги якої відповідають проектам, а підкаталог .metadata
використовується як сховище налаштувань і даних. Є також можливість імпортувати у робочий простір проекти з інших тек.
Після першого завантаження Eclipse на екрані з'являється стартове вікно інтеґрованого середовища ("Welcome to the Eclipse IDE for Java Developers"). Далі можна закрити вікно "Welcome" та, якщо треба, змінити робочий простір. Для того, щоб почати роботу з Java-проектом, необхідно визначити відповідну перспективу (Window | Open Perspective | Other... | Java). Найчастіше ця перспектива є усталено обраною.
Якщо робочий простір був створений раніше, розкривається робоче вікно, яке містить підвікна перегляду та редагування ресурсів згідно з обраною раніше перспективою. Непотрібні вікна редагування доцільно закрити. Можна продовжувати роботу над попередніми проектами, або створювати новий.
2.2.2 Створення нового проекту
Для створення нового проекту слід застосувати функцію File | New | Project... головного меню середовища Eclipse. Далі обираємо Java | Java Project (Адаптоване меню передбачає скорочений шлях – File | New | Java Project). Натискаємо кнопку Next. Далі слід набрати ім'я проекту на натиснути Finish.
Примітка: Опція Use project folder as root for sources and class files передбачає, що вихідні та скомпільовані файли містяться в спільних теках. Опція Create separate folders for sources and class files передбачає створення двох окремих паралельних ієрархій тек вихідних і скомпільованих файлів. Ця опція обрана усталено і є рекомендованою.
Усі функції у мові програмування Java реалізуються у контексті класів. Необхідно спроектувати клас, який повинен принаймні містити статичний метод main()
, з якого починається виконання програми на Java. У найпростішому випадку такому класу не потрібні ані поля, ані інші методи. Функція File | New | Class здійснює активізацію майстра класів. За допомогою майстра класів до проекту додається новий файл з вихідним текстом, який містить опис класу. Для майбутнього класу треба визначити ім'я пакету, у який він входить, ім'я класу, (public або default, іноді додатково abstract та final) та ім'я базового класу (Superclass). Створення консольної програми передбачає вибір базового класу java.lang.Object
. Якщо це треба, до класу можна додати перелік інтерфейсів, які він реалізує.
Для виконання завдання роботи треба включити опції "public" (генерація класу, методи якого можуть використовуватись за межами пакету) та "public static void main(String[] args)" (генерація статичного методу main()
). У більш складних програмах класу може бути потрібне перекриття конструкторів базового класу (опція " Constructors from superclass"). У нашому випадку конструктор взагалі не потрібен, бо клас не матиме нестатичних даних. Коли базовим класом не є абстрактний клас, відсутня необхідність у перекритті абстрактних методів (опція "Inherited abstract methods"). Опція "Generate comments" (генерація коментарів) використовується для автоматичного створення програмної документації.
Припустимо, створено пакет з назвою test
та обрано ім'я класу TestClass
. Після натиснення кнопки ОК створюється файл TestClass.java
, який містить такий код:
package test; public class TestClass { public static void main(String[] args) { // TODO Auto-generated method stub } }
Метод main()
класу повинен бути загальнодоступним (public
), статичним (static
) та не повертати результату (void
). Заголовок функції main()
містить у списку параметрів масив рядків String[] args
. Це аргументи командного рядку. Після заголовку методу проміж згенерованими фігурними дужками вписуються оператори тестової програми.
Для тестування можна запропонувати такий текст:
package test; public class TestClass { public static void main(String[] args) { int i = 2; int j = 2; System.out.println(i * j); } }
Для виведення результату 2 * 2
на консоль здійснюється виклик методу println()
статичного поля out
класу System
.
Для того, щоб виконати програму, слід створити конфігурацію виконання. У найпростішому випадку можна скористатися функцією Run | Run As | Java Application головного меню (або Run As | Java Application контекстного меню). У нижній частині вікна з'являється спеціальне консольне підвікно (Console).
Якщо необхідно установити додаткові параметри, наприклад опції командного рядку, слід скористатися функцією головного меню Run | Run Cofigurations.... Серед конфігурацій обирають "Java Application". Після натискання кнопки New контекстного меню змінюється вміст вікна, де обирають ім'я проекту (Project) та головного класу (Main class). Далі можна закрити вікно або здійснити виконання (Run). У наступному можна використовувати зелену кнопку "Run" (або Ctrl-F11).
Якщо проект був створений раніше на іншому комп'ютері, його можна скопіювати в теку, яка представляє робочий простір, а потім імпортувати проект за допомогою функції імпорту (File | Import... General | Existing Project into Workspace). Імпорт не передбачає фізичного копіювання файлів проекту.
2.2.3 Зневадження програми
Засоби зневадження (налагодження, debug) використовуються для пошуку та виправлення помилок часу виконання. Для запуску цих засобів використовується спеціальна перспектива – Debug, яку можна розкрити за допомогою функції Window | Open Prespective | Debug. Далі у вихідному тексті розставляються точки переривання (функція Run | Toggle Line Breakpoint або Ctrl-Shift-B). Для запуску програми у режимі зневадження використовуємо функцію Run | Debug F11 головного меню. Для виконання програми по рядках використовуються функції Step Into (F5, покрокове виконання із заходженням у функції) та Step Over (F6, без заходження в функції).
Якщо помістити курсор миші на скалярну змінну, зневаджувач покаже її значення в маленькому віконці.
Продовжити виконання можна за допомогою функції Run | Resume. Припинити виконання можна за допомогою функції Run | Terminate.
2.3 Базові засоби мови Java
2.3.1 Загальна структура програми мовою Java. Особливості виконання програми
У Java немає глобальних змінних, функцій чи процедур. Це зроблено з метою запобігання конфліктів імен. Програма складається з одного чи більше описів класів з полями (елементами даних) і методами (функціями-елементами). Класи в Java можуть мати модифікатор public
Такі класи мають назву відкритих (публічних). Один із відкритих класів повинен визначати статичний метод main()
, з якого починається виконання програми. Програмний код визначення класів слід зберігати у текстових файлах з розширенням .java
. Ім'я класу (без розширення) повинне збігатися з іменем публічного класу, який міститься у цьому файлі. Слід пам'ятати, що великі й маленькі літери відрізняються.
Кожен клас компілюється в окремий файл, що містить двійковий код і має розширення .class
. На відміну від С++, це не команди процесора, а байт-коди.
Скомпільована програма може бути виконана на комп'ютері, лише якщо на ньому встановлена так звана віртуальна машина Java (JVM, Java Virtual Machine) – спеціальна програма, яка здійснює інтерпретацію байт-кодів. Такий підхід дозволяє створювати програми, які можна переносити з одного операційного середовища (операційної системи, апаратної платформи) на інше без додаткової перекомпіляції. На відміну від C++, Java не передбачає статичного компонування коду у файл, який може бути виконано (.exe
). Компонування (отримання байт-коду з різних файлів з розширенням .class
або зі спеціальних архівів та інтерпретація коду) здійснюється динамічно.
2.3.2 Ідентифікатори, ключові та зарезервовані слова. Коментарі
Як і в C++, у мові Java відрізняються великі та маленькі літери.
Вихідний текст Java складається з лексем. Лексема (token) – це послідовність символів, що мають певне сукупне значення. Проміж окремими лексемами розташовують розділювачі – пропуск, табуляція, новий рядок тощо.
Лексеми поділяються на такі групи:
- ключові (зарезервовані) слова
- ідентифікатори
- літерали (константи)
- знаки операцій.
Набір ключових слів обмежений. Усі ключові слова є зарезервованими. Ключові слова не можна використовувати як ідентифікатори. У Java також існують зарезервовані слова, які не є ключовими. Їх взагалі не можна використовувати. Це const
та goto
.
Ідентифікатори використовуються для іменування змінних, функцій та інших програмних об'єктів. Першим символом повинна бути літера чи символ підкреслення ("_", underscore character). Далі можуть використовуватися також цифри. Використання символу підкреслення на початку імені не є бажаним.
Доцільно використовувати змістовні імена, які відображають природу об'єкта або функції. Не можна використовувати пропуски всередині ідентифікатора. Тому, якщо необхідно створити ідентифікатор з кількох слів, ці слова пишуть злито, починаючи друге, третє та інші слова з великої літери. Наприклад, можна створити таке ім'я змінної:
thisIsMyVariable
Для змістовних імен доцільно використовувати англійську мнемоніку. Імена класів та інтерфейсів слід починати з великої літери, інші імена – тільки з маленької. Імена статичних констант складаються з великих літер та символу підкреслення, наприклад PI
, CONST_VALUE
тощо.
Коментарі – це текст всередині вихідного коду, який не обробляє компілятор. Мова Java підтримує три види коментарів:
- у стилі C++ (
//
до кінця рядка) - у стилі C (
/* */
) - коментарі Javadoc (
/** */
).
Спеціальний засіб javadoc.exe, що входить у JDK (Java Development Kit), використовує коментарі третього виду для автоматичної генерації документації. Для цього такі коментарі повинні бути відформатовані за стандартом Javadoc. Можна додавати коментарі для рівня класів і інтерфейсів, а також для рівня методів і полів. Коментарі Javadoc повинні бути розташовані перед відповідними фрагментами коду. Кожен коментар складається з опису і тегів. У коментарі javadoc можна включати теги форматування HTML. Не рекомендується включати теги, що забезпечують виведення жирним шрифтом, курсивом і т. д. Є спеціальний набір тегів Javadoc, таких як @author
, @param
, @return
і т. д. Ці теги забезпечують стандартне представлення документації, що стосується класів і методів. Наприклад, такі коментарі перед методом
/** * Повертає ім'я файлу з відповідним індексом.<br> * Імена файлів зберігаються в масиві рядків. * @param i індекс * @return ім'я файлу. * */ public String getFileName(int i) { return names[i]; }
забезпечують генерацію такого фрагмента HTML-файлу документації:
Method Detail |
getFileName
public String getFileName(int i)
- Повертає ім'я файлу з відповідним індексом.
Імена файлів зберігаються в масиві рядків.
- Parameters:
i
– індекс- Returns:
- file ім'я файлу.
2.3.3 Визначення локальних змінних. Примітивні типи
Локальні змінні визначаються (створюються) всередині методів. Опис локальних змінних у Java здійснюється аналогічно C++. Наприклад:
int i = 11; double d= 0, x; float f; int j, k;
Локальні змінні можуть бути визначені в будь-якому місці усередині тіла функції, а також у вкладеному блоці. У Java не можна у внутрішньому блоці визначати імена, вже описані в зовнішньому блоці:
{ int i = 0; { int j = 1; // Змінна j визначається у внутрішньому блоці int i = 2; // Помилка! Змінна i визначена в зовнішньому блоці } }
У Java не можна оголошувати змінні без їхнього створення.
Ключове слово final
стосовно до імен змінних означає, що вони не можуть бути змінені.
final int h = 0;
Слово const
зарезервоване, але не використовується.
Примітивні, чи базові типи поділяються на цілі типи, типи з крапкою, що плаває, символьні і булеві. Примітивні типи приведені в наведеній нижче таблиці.
Таблиця 2.1 – Примітивні типи даних
Ключове слово | Опис | Розміри |
---|---|---|
Цілі типи | ||
byte |
маленьке ціле (від -128 до 127) | 8 біт |
short |
коротке ціле (від -32768 до 32767) | 16 біт |
int |
ціле (від -2147483648 до 2147483647) | 32 біта |
long |
довге ціле (від -9223372036854775808 до 9223372036854775807) | 64 біта |
Типи з плаваючою крапкою | ||
float |
дійсне число звичайної точності | 32 біта |
double |
дійсне число подвійної точності | 64 біта |
Інші типи | ||
char |
символ у кодах Unicode | 16 біт |
boolean |
булеве значення (true або false ) |
У багатьох інших мовах (наприклад, у С та у С++) формат і розміри примітивних типів даних залежать від платформи (DOS, Win 32 і т. д.). У Java розміри і формат стандартизовані і не залежать від платформи.
Константи цілого типу записуються як послідовності десяткових цифр. Усталений тип константи – int
. Він може бути уточнений додаванням наприкінці константи літер L
чи l
(тип long
). Цілі константи можуть записуватися у вісімковій системі числення, у цьому випадку першою цифрою повинна бути цифра 0, число може містити тільки цифри 0...7. Цілі константи можна записувати й у шістнадцятковій системі числення, у цьому випадку запис константи починається із символів 0x
чи 0X
. Для позначення цифр понад 9 використовуються латинські літери a
, b
, c
, d
, e
та f
(великі або маленькі). Наприклад:
int octal = 023; // 19 int hex = 0xEF; // 239
У Java 7 з'явилася можливість визначати також двійкові константи (з використанням префіксів 0B
або 0b
):
int m = 0b110011; // 51
Крім того, групи розрядів у константах можна розділяти знаком підкреслення, наприклад: int n = 1_048_576;
Константи типу char
беруть в одиночні лапки (апострофи), значення константи задається або знаком з поточного набору символів, або цілою константою, якій передує зворотна коса риска (символ із заданим кодом). Є ряд спеціальних символів, що можуть використовуватись як значення константи типу char
(такі подвійні символи називаються керуючими послідовностями):
'\n' – новий рядок, '\t' – горизонтальна табуляція, '\r' – переведення на початок рядку, '\'' – одиночні лапки (апостроф), '\"' – подвійні лапки, '\\' – зворотна коса риска (backslash).
Для зберігання даних символьного типу в пам'яті використовується таблиця Unicode.
Константи дійсних типів можуть записуватись у формі з крапкою або в експонентному форматі та усталено мають тип double
. При необхідності тип константи можна уточнити, записавши наприкінці суфікс f
чи F
для типу float
, суфікс d
чи D
для типу double
. Наприклад:
1.5f // 1.5 типу float 2.4E-2d // 0.25 типу double
Значення з плаваючою крапкою не можна присвоювати цілим змінним. Перетворення до більш вузького типу (дійсного до цілого, числа з подвійною точністю до числа з одинарною точністю) пов'язано з ризиком утрати даних і повинне здійснюватися явно:
int i = 10; float f = i; // Таке перетворення допускається long l = f; // Помилка! long l1 = (long) f; // Явне приведення типів
Числа без десяткової крапки інтерпретуються як цілі (типу int
). Числа з плаваючою крапкою мають тип double
. Для приведення їх до більш вузьких типів використовується явне приведення типів:
float f = 10.5; // Помилка! float f1 = (float) 10.5; // Явне приведення типів float f2 = 10.5f; // Уточнення типу константи. Помилки немає
У Java немає беззнакових (unsigned) цілих типів.
Булевим змінним можна присвоювати тільки константи true
та false
. Змінні типу boolean
не можна неявно чи явно приводити до інших типів і навпаки.
Константа-рядок складається із символів, які беруть у подвійні лапки. Наприклад:
"Це рядок"
Результат додавання рядку до змінної іншого типу забезпечує перетворення значення у представлення у вигляді рядка. Зокрема, такий підхід застосовують для виведення значень декількох змінних. Наприклад:
int k = 1; double d = 2.5; System.out.println(k + " " + d); // 1 2.5
2.3.4 Вирази та операції
Всередині методів класів, з яких складається програма, можуть міститись твердження (оператори), які, в свою чергу, складаються з виразів. Вираз складається з однієї чи кількох операцій. Об'єкти операцій мають назву операндів. Операції бувають унарними (один операнд), бінарними (два операнда) і тернарними (три операнда).
У Java підтримуються практично всі стандартні арифметичні і логічні операції, а також операції порівняння мови С++. Ці операції мають такий же пріоритет і асоціативність, як і в C++.
До арифметичних операцій належать +, -
(бінарні й унарні), *
, /
а також операція отримання залишку від ділення %
(тільки до цілих). Якщо /
застосовується до цілих, результатом ділення буде теж ціле, а залишок відкидається. Якщо хоча б один операнд – типу з плаваючою крапкою (дійсний), ми отримаємо дійсний результат.
System.out.println(1 / 2); // 0 System.out.println(1.0 / 2); // 0.5
До операцій відношення належать перевірка на рівність ==
і на нерівність !=
, а також перевірки >
(більше) >=
(більше або дорівнює) <
(менше) <=
(менше або дорівнює). До логічних операцій належать логічне І (&&
), АБО (||
) та НІ (!
). Операції відношення та логічні повертають значення типу boolean
. Операції І та АБО можна застосовувати побітові &
і |
. У такому випадку завжди здійснюється повне обчислення значень обох операндів, тоді як обчислення значення другого операнду операцій &&
і ||
може не здійснюватись, якщо результат вже встановлено.
До операцій присвоювання відносяться операції простого і складеного присвоювання. Результатом операції простого присвоювання є значення того виразу, що присвоюється лівому операнду. Складене присвоювання можна представити в загальному вигляді в такий спосіб:
a op= b
У цьому випадку op – арифметична чи побітова операція: + - * / % | & ^ << >>
. Кожна складена операція еквівалентна присвоюванню:
a = (a) op (b);
Наприклад,
x += 5;
що еквівалентно
x = x + 5;
Операція інкременту ++ забезпечує збільшення цілої змінної на одиницю. Вона має дві форми префіксну і постфіксну. Префіксна форма забезпечує збільшення змінної до того, як значення операції буде використано, а постфіксна – після. Операція декременту --
забезпечує зменшення змінної на одиницю і правила її використання аналогічні.
На відміну від C++, операція "кома" може бути застосована тільки в заголовках циклів, наприклад:
int i, j; for (i = 0, j = 0; i < 10; i++, j += 2) { System.out.println(i + " " + j); }
Використання побітових операцій &
(побітове І), |
(побітове АБО), ^
(виключальне АБО), ~
(побітове не), <<
та >>
(побітовий зсув) аналогічне С++. У Java існує додаткова операція беззнакового зсуву (>>>
).
Умовна операція (тернарна) має такий вигляд:
умова ? вираз1 : вираз2
Спочатку обчислюється значення умови. Якщо воно істинне, то обчислюється вираз1
і його значення повертається умовною операцією. Якщо значення умови хибне, то обчислюється вираз2
і повертається його значення. У наведеному нижче прикладі обчислюється мінімальне з двох чисел:
min = a < b ? a : b;
Порядок застосування унарних операцій та операцій присвоєння "справа наліво", а всіх інших операцій – "зліва направо".
Пріоритет додавання і віднімання нижче, ніж множення і ділення, пріоритет присвоєння нижче, ніж арифметичних операцій і т.д. Для зміни послідовності операцій слід використовувати дужки.
У Java не допускається безпосередня робота з указівниками, отже, немає операцій розіменування, вибору елемента за вказівником і узяття адреси (*
, ->
та &
).
У Java немає операції sizeof
() оскільки її головне призначення в С++ – з'ясовувати розміри тих чи інших даних під час перенесення вихідного тексту на іншу платформу. У Java розміри всіх типів стандартизовані.
2.3.5 Твердження (інструкції). Керування виконанням програми
Твердження (або інструкція, іноді оператор, англ. statement) – найменша автономна частина мови програмування. Програма являє собою послідовність інструкцій. Більшість тверджень мови Java аналогічна твердженням C++.
Порожня інструкція складається з однієї крапки з комою.
Інструкція-вираз є повний вираз, який закінчується крапкою з комою. Наприклад:
k = i + j + 1;
Складена інструкція – це послідовність тверджень, укладена у фігурні дужки. Складену інструкцію часто іменують блоком. Після фігурної дужки, яка закриває блок, крапка з комою не ставиться. Синтаксично блок може розглядатися як окрема інструкція, однак вона також має значення у визначенні видимості і часу життя ідентифікаторів. Ідентифікатор, оголошений усередині блоку, має область видимості від точки визначення до фігурної дужки, що закривається. Блоки можуть необмежено вкладатися один в одного.
Інструкції вибору – умовна інструкція та перемикач. Умовна інструкція застосовується в двох видах:
if (вираз-умова) інструкція1 else інструкція2
або
if (умова) інструкція1
Під час виконання цієї інструкції обчислюється вираз-умова і, якщо це істина, то виконується інструкція1 а інакше – інструкція2. На відміну від C++, вираз-умова може бути лише типу boolean
.
Перемикач дозволяє вибрати одну з кількох можливих гілок обчислень і будується за схемою:
switch (цілий_вираз) блок
Блок має такий вигляд:
{ case константа_1: інструкції case константа-2: інструкції ... default: інструкції }
Виконання перемикача полягає в обчисленні керуючого виразу і переході до групи інструкцій, позначених case
-міткою, значення якої дорівнює керуючому виразу. Якщо такої мітки немає, виконуються інструкції після мітки default
(яка може бути відсутня). Під час виконання перемикача відбувається перехід на інструкції з обраною міткою і далі інструкції виконуються у нормальному порядку. Для того, щоб не виконувати інструкцій, які залишилися у тілі перемикача, необхідно використовувати оператор break
.
Примітка: починаючи з Java 7, окрім цілих та символів, у конструкції switch
()
можна використовувати рядки. В цьому випадку константи варіантів (після case
) повинні теж бути рядками, наприклад:
case "some text":
Інструкції циклу реалізовані в трьох варіантах: цикл із передумовою, цикл із постумовою і цикл із параметром.
Цикл із передумовою будується за схемою
while (вираз-умова) інструкція
На кожному повторенні циклу обчислюється вираз-умова і якщо значення цього виразу дорівнює true
, виконується інструкція – тіло циклу.
Цикл із постумовою будується за схемою
do інструкція while (вираз-умова);
Вираз-умова обчислюється і перевіряється після кожного повторення інструкції – тіла циклу, цикл повторюється, поки умова виконується. Тіло циклу в циклі з постумовою виконується принаймні один раз.
Цикл із параметром будується за схемою:
for (E1; E2; E3) інструкція
де E1
, E2
і E3
– вирази скалярного типу. Цикл з параметром реалізується за таким алгоритмом:
- обчислюється вираз
E1
(зазвичай цей вираз виконує підготовку до початку циклу); - обчислюється вираз
E2
і якщо він дорівнюєfalse
, виконується перехід до наступної інструкції програми (вихід з циклу); - якщо
E2
дорівнюєtrue
, виконується інструкція – тіло циклу; - обчислюється вираз
E3
– виконується підготовка до повторення циклу, після чого знову виконується виразE2
.
У наведеному нижче прикладі сума
y = 12 + 22 + 32 + ... + n2
знаходиться за допомогою трьох різних циклічних інструкцій.
За допомогою циклу while
:
int y = 0; int i = 1; while (i <= n) { y += i * i; i++; }
За допомогою циклу do ... while
:
int y = 0; int i = 1; do { y += i * i; i++; } while (i <= n);
За допомогою циклу for
:
int y = 0; for (int i = 1; i <= n; i++) { y += i * i; }
Циклічні конструкції можна вкладати одну в іншу.
У сполученні з інструкціями циклу використовуються інструкції переходу – оператор break
, який дозволяє перервати виконання найвнутрішнішого з циклів, оператор continue
, який перериває поточну ітерацію найвнутрішнішого з циклів while
, do
або for
. Найчастіше break
використовують у такій конструкції:
if (умова_дострокового_завершення_циклу) break;
У Java після ключових слів break
та continue
можна розташувати мітку, що передує одному з вкладених циклів. У цьому випадку твердження стосуються не до найвнутрішнішого, а до позначеного циклу. Наприклад:
int a; . . . double b = 0; label: for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { if (i + j + a == 0) { break label; } b += 1.0 / (i + j + a); } }
Твердження goto
не використовується в мові Java, але goto
є зарезервованим словом. Це слово ніяк не може бути використано.
У Java немає оператора typedef
. Мова Java також не підтримує типів struct
та union
.
2.4 Пакети та функції
У Java немає заголовних файлів. Для боротьби з можливими конфліктами імен уся глобальна область видимості розділяється на пакети.
Пакет – це набір взаємозалежних класів та інших елементів коду, які здійснюють взаємодію один з одним через загальний доступ до функцій і даних і через загальний простір імен. Усі вихідні файли одного пакету повинні міститися в одній теці. Пакети можуть вкладатися один в інший. Кожен клас Java знаходиться в будь-якому пакеті. Імена пакетів повинні збігатися з іменами тек, у яких знаходяться файли вихідного тексту (чи скомпільовані файли).
У першому рядку вихідного файлу (не враховуючи порожніх рядків і коментарів) найчастіше знаходиться заголовок пакету, до якого відносяться класи, визначені у файлі.
package package_name;
Якщо ім'я пакета пропущене, вважається, що код відноситься до безіменного пакету (усталеного пакету), межі якого визначаються поточною текою. До класів та інших синтаксичних конструкцій такого пакету не можна звернутися ззовні. Такий варіант не є бажаним.
Бажано використовувати більш змістовні імена пакетів. Можна створювати вкладені пакети, відповідно створюючи вкладені теки. Крім того, бажано забезпечити унікальність імен пакетів. Для забезпечення унікальності можна використовувати обернене доменне ім'я. Наприклад, якщо доменне ім'я автора author.com
, то слід використовувати пакет com
, далі підпакет author
і далі підпакети, відповідно до різних задач. Далі в прикладах використовуватиметься пакет ua.inf.iwanoff
, що є оберненим доменним ім'ям автора. У цьому пакеті створюватимуться підпакети.
У Java немає глобальних функцій. Аналогом глобальної функції є статичний метод. Опис статичної функції у найпростішому випадку має таку структуру:
static тип_результату ім'я_функції(список_формальних_параметрів) тіло
Параметри (аргументи) функції, що вказуються в списку у визначенні функції, називаються формальними. Параметри, що вказуються під час виклику функції, називаються фактичними. Під час виклику функції виділяється пам'ять під її формальні параметри, потім кожному формальному параметру присвоюється значення фактичного параметра.
Тіло функції являє собою складений оператор (блок). Наприклад, визначення статичної функції, що обчислює суму двох цілих чисел, може бути таким:
static int sum(int a, int b) { int c = a + b; return c; }
Можна взагалі обійтися без змінної с:
static int sum(int a, int b) { return a + b; }
Виклик функції може бути здійснений у виразі в описі або в тілі іншої функції. Під час виклику функції вказується її ім'я і список фактичних параметрів без зазначення їхніх типів:
int x = 4; int y = 5; int z = sum(a, b); int t = sum(1, 3);
Функція може бути без параметрів:
int zero() { return 0; }
Викликаючи таку функцію, також необхідно використовувати дужки:
System.out.println(zero());
Інструкція return
у тілі функції забезпечує завершення роботи функції. Значення виразу після return
стає значенням функції, яке ця функція повертає.
Функція може не повертати ніякого результату. Для позначення цього використовується тип void
.
void hello() { System.out.println("Hello!"); }
У цьому випадку в тілі функції return
може бути відсутнім. Якщо інструкція return
присутня, то після неї не повинно бути ні якого виразу. Таку функцію можна викликати тільки окремою інструкцією.
hello();
Параметри передаються до функцій за значенням, тобто значення фактичних параметрів копіюються в пам'ять, відведену для формальних параметрів. При цьому значення, з якими працює функція – це її власні локальні копії фактичних параметрів і їхня зміна на ці параметри не впливає. Таким чином, під час передачі за значенням вміст фактичних параметрів не змінюється:
static void f(int k) { k++; // k = 2; } public static void main(String[] args) { int k = 1; f(k); System.out.println(k); // k = 1; }
У Java можна перевантажувати імена функцій. Перевантаженням імені називається його використання для позначення різних операцій над різними типами.
Якщо списки формальних параметрів збігаються, але типи значень, що повертаються, різні, компілятор повідомляє про помилку. Якщо списки формальних параметрів двох функцій розрізняються числом чи параметрів їхніми типами, то ці дві функції вважаються перевантаженням однієї функції і повинні мати різні визначення.
Перевантажені функції використовуються в тих випадках, якщо кілька функцій виконує схожі дії над об'єктами різних типів і зручно дати однакові імена всім цим функціям:
static int max(int a, int b) { } // Вибір максимального з двох цілих чисел static int max(double x, double y, double z) { } // Вибір максимального з трьох дійсних чисел
Для того, щоб визначити, яку саме функцію варто викликати, порівнюються кількість і типи фактичних параметрів, зазначені у виклику, з кількістю і типами формальних параметрів всіх описів функцій з таким ім'ям. У результаті викликається та функція, у якої формальні параметри щонайкраще зіставилися з параметрами виклику, чи видається помилка, якщо такої функції не знайшлося.
Дефолтні параметри функції, які можуть бути описані у С++, у Java не застосовуються.
Статичні функції в межах класу викликаються з застосуванням лише імені функції та списку фактичних параметрів. Для того, щоб викликати статичну функцію іншого класу, необхідно вказувати його ім'я і далі через точку ім'я функції. В такий спосіб можна звертатись до імен у межах пакету, а також до класів і функцій пакету java.lang
. Цей пакет містить класи з дуже корисними функціями. Наприклад, клас Math
надає велику кількість математичних функцій.
Таблиця 2.2 – Найбільш вживані математичні функції класу Math
Функція |
Зміст |
Приклад виклику |
double pow(double a, double b) |
Обчислення ab |
Math .pow(x, y) |
double sqrt(double a) |
Обчислення квадратного кореня |
Math .sqrt(x) |
double sin(double a) |
Обчислення синуса |
Math .sin(x) |
double cos(double a) |
Обчислення косинуса |
Math .cos(x) |
double tan(double a) |
Обчислення тангенса |
Math .tan(x) |
double asin(double a) |
Обчислення арксинуса |
Math .asin(x) |
double acos(double a) |
Обчислення арккосинуса |
Math .acos(x) |
double atan(double a) |
Обчислення арктангенса |
Math .atan(x) |
double exp(double a) |
Обчислення ex |
Math .exp(x) |
double log(double a) |
Обчислення натурального логарифма |
Math .log(x) |
double abs(double a) int abs(int a) |
Знаходження модуля числа |
Math .abs(x) |
long round(double a) |
Округлення до найближчого цілого |
Math .round(x) |
Крім математичних функцій, клас Math
надає такі корисні константи, як Math.PI
, Math.E
.
Якщо класи знаходяться в інших пакетах (не у java.lang
), для виклику цих функцій слід або застосовувати префікс – ім'я_пакету.ім'я_класу
. Якщо необхідні класи вкладених пакетів, префікс буде ще більш складним. Для того, щоб запобігти використанню повних імен, застосовується конструкція import
. Конструкції import
розташовують на початку файлу з вихідним кодом, або безпосередньо після конструкції package
.
Для забезпечення доступу до класу чи інтерфейсу з іншого пакету є три варіанти:
- Імпорт класу чи інтерфейсу (
import ім
'я_пакету.імпортоване_ім'я
). - Імпорт усього пакету (
import
). - Статичний імпорт – імпорт статичних елементів зазначеного класу.
Наведений нижче приклад демонструє перші два варіанти:
import java.io.FileReader; // Імпорт класу (інтерфейсу) import java.util.*; // Імпорт усього пакету public class TestClass { public static void main(String[] args) { java.io.FileWriter fw; // Повне ім'я FileReader fr; // Прямий доступ до імпортованого імені ArrayList al; // ArrayList входить у пакет java.util . . . } }
Не слід включати в програму твердження import
java.lang.*
. Цей пакет імпортується автоматично.
Додаткова форма імпорту, яка з'явилася у версії Java 5, дозволяє імпортувати тільки статичні елементи зазначеного класу. Наприклад, у програмах, які реалізують математичні обчислення доцільно додавати статичний імпорт елементів класу Math
:
import static java.lang.Math.*;
Тепер статичні елементи можна використовувати без додаткового кваліфікатору, наприклад:
double d = sin(1);
2.5 Консольне введення та виведення
Для забезпечення консольного введення Java надає декілька варіантів:
- безпосереднє використання потоку введення
System.in
, зокрема його функціїread()
; - використання класу
java.io.Console
; - використання класу
java.util.Scanner
.
Перший варіант – низькорівневий і вимагає великої кількості "ручної роботи", тому зараз майже не застосовується. Другий варіант (клас java.io.Console
, починаючи з JDK 1.6) теж має певні недоліки, зокрема, інтегровані середовища Eclipse і IntelliJIDEA не підтримують роботу з об'єктами цих класів у своїх консольних вікнах.
Найбільш зручним засобом уведення даних є клас java.util.Scanner
. Клас Scanner
надає функції для читання даних з різних джерел, наприклад, з файлів. У нашому випадку ми вказуємо на необхідність читання з клавіатури (стандартний потік введення System.in
). Об'єкт-сканер можна застосувати для читання даних різних типів. Наприклад, функція next()
повертає наступне прочитане значення типу String
(рядок), nextInt()
дозволяє отримати ціле, nextDouble()
повертає прочитане число типу double
. Є також функції nextBoolean()
, nextByte()
, nextShort()
, nextLong()
, nextFloat()
тощо. Усі функції обумовлюють зупинку виконання програми, яке поновлюється після введення з клавіатури відповідного значення.
Для можливості роботи з класом Scanner
на початку вихідного коду слід додати:
import java.util.Scanner;
Це дозволить використовувати ім'я Scanner
без додаткового префіксу.
Спочатку треба створити об'єкт цього класу за допомогою операції new
(докладно ця операція буде розглянута пізніше). Зв'язуємо об'єкт-сканер зі стандартним System.in
. Далі можна читати дані різних типів. Наприклад:
package ua.inf.iwanoff.labs.fourth; import java.util.Scanner; public class ScannerTest { @SuppressWarnings("resource") public static void main(String[] args) { Scanner scanner = new Scanner(System.in); String s = scanner.next(); // читання рядка double d = scanner.nextDouble(); // читання дійсного числа int i = scanner.nextInt(); // читання цілого числа // ... використання введених даних } }
Примітка: Аннотація @SuppressWarnings("resource")
додана для того, щоб компілятор не вимагав закрити потік, пов'язаний з об'єктом scanner
. Стандартні консольні потоки не передбачають закриття.
Великою зручністю класу є можливість довільного розташування даних у вхідному потоці: окремі дані можна розділяти пропусками, табуляцією, або переведенням рядка. Єдиний виняток – використання функції nextLine()
, яка читає дані до кінця рядка.
Виведення у консольне вікно здійснюється за допомогою функцій об'єкта out
класу System
. Функція print()
дозволяє вивести результат без переходу на новий рядок, println()
здійснює перехід на новий рядок після виведення.
Можна також скористатися функцією printf()
для форматованого виведення. Використання цього методу аналогічне використанню відповідної функції мови С. Перший параметр – так званий рядок форматування. Далі можна вказати довільну кількість параметрів, значення яких слід вивести на консоль. Наприклад:
double d = 3.5; int i = 12; System.out.printf("%f %d%n", d, i);
Використовують такіспецифікатори формату:
Специфікатор формату |
Форматування яке здійснюється |
%a |
Шістнадцяткове значення з плаваючою точкою |
%b |
Логічне (булеве) значення аргументу |
%c |
Символьне представлення аргументу |
%d |
Десяткове ціле значення аргументу |
%e |
Експоненціальне подання аргументу |
%f |
Десяткове значення з плаваючою точкою |
%g |
Вибирає більш коротке представлення з двох: |
%o |
Вісімкове ціле значення аргументу |
%n |
Вставка символу нового рядка |
%x |
Шістнадцяткове ціле значення аргументу |
%% |
Вставка символу % |
Після символу % можна вказувати ширину поля.
Є також можливість виведення повідомлень у потік System.err
(стандартний потік повідомлень про помилки). Виведення в цей потік має більш високий пріоритет, ніж виведення в System.out
, тому іноді повідомлення про помилки випереджають "нормальне" виведення.
2.6 Запуск Java-застосунків з командного рядку
Скомпільовані програми можуть бути запущені в командному рядку. Для запуску командного рядка в Windows використовується команда cmd
. У командному рядку запускається віртуальна машина Java (команда java
), далі через пропуск указується параметр -classpath
(чи -cp
), після якого через пробіл вказується повний шлях до каталогу проекту. Далі вказується ім'я пакета і через крапку ім'я класу, що містить функцію main()
.
Припустимо, проект First
створений у робочому просторі, зв'язаним з текою E:\eclipse\workspace
, а функція main()
реалізована в класі TestClass
пакету first
. Для запуску програми в командному рядку варто набрати
java -cp E:\eclipse\workspace\First first.TestClass
Під час виведення на консоль у Windows символів кирилиці можуть виникнути проблеми. Їх можна вирішити, вказавши віртуальній машині кодову сторінку DOS за допомогою параметра -Dfile.encoding=IBM-866
:
java -Dfile.encoding=IBM-866 -cp E:\eclipse\workspace\First\bin first.TestClass
3 Приклади програм
3.1 Середнє арифметичне
Необхідно ввести з клавіатури два числа (дійсне та ціле) і обчислити їх середнє арифметичне.
У середовищі Eclipse створюємо новий проект. У новому проекті створюємо пакет
ua.inf.iwanoff.labs.first
, до якого додаємо клас Average
. Під час генерації класу вказуємо на необхідність створення функції main()
. Одержуємо такий код:
package ua.inf.iwanoff.labs.fourth; public class Average { public static void main(String[] args) { // TODO Auto-generated method stub } }
Тепер замість коментаря всередині функції maіn()
створюємо об'єкт класу Scanner
, описуємо дві змінні, наприклад, a
і b
, читаємо їхні значення з клавіатури і обчислюємо значення c
, що є їхнім середнім арифметичним.
Scanner s = new Scanner(System.in); double a = s.nextDouble(); int b = s.nextInt(); double c = (a + b) / 2;
Для забезпечення можливості використання класу Scanner
слід перед описом класу Average
додати інструкцію імпорту (import
java.util.Scanner;
). Визначення (опис) змінної, як і в C++, можна поєднувати з присвоєнням початкового значення (ініціалізацією). У цьому випадку створюється змінна s типу Scanner
, b
типу int
, а також змінні a
і c
типу double
.
Після ініціалізації змінної c необхідний результат вже обчислений. Його необхідно вивести на екран (у консольне вікно) з використанням функції println()
об'єкта out
класу System
.
System.out.println("Середнє арифметичне: " + c);
У цьому рядку плюс означає не додавання, а зшивання рядків. До строкової константи "Середнє арифметичне: "
пришивається рядкове представлення значення змінної c
.
Тепер можна навести повний текст програми.
package ua.inf.iwanoff.labs.fourth; import java.util.Scanner; public class Average { public static void main(String[] args) { Scanner s = new Scanner(System.in); double a = s.nextDouble(); int b = s.nextInt(); double c = (a + b) / 2; System.out.println("Середнє арифметичне: " + c); } }
Після запуску програми слід перейти у підвікно Console, увести в різних рядках значення a
та b
, після чого в консольному вікні з'явиться результат.
3.2 Степені числа 2
Необхідно ввести n
(1 до 30 включно) та вивести на екран степені числа 2 – від першого до введеного n-го. Можна реалізувати два варіанти – з використанням арифметичних дій і побітових операцій.
3.2.1 Використання арифметичних операцій
До попереднього пакету додаємо клас Powers
. Для виконання однотипних дій доцільно створити цикл, у тілі якого обчислюється черговий степінь 2 та виводиться на екран. Реалізація алгоритму мовою Java матиме такий вигляд:
Scanner s = new Scanner(System.in); int n = s.nextInt(); int k = 2; // основа степеня int power = 1; for (int i = 1; i <= n; i++) { power *= k; System.out.printf("2 ^ %2d = %d\n", i, power); }
У цьому прикладі для опису змінних використовується тип int
(цілий), тому що і основа степеня, і показник, і степінь – цілі числа. Початкове значення результату
int power = 1;
є типовим для обчислення добутків послідовностей Як видно з прикладу, параметр циклу можна визначати безпосередньо в заголовку циклу. Для множення, як і в інших мовах програмування, використовується знак зірочки. Замість традиційного для багатьох мов твердження
power = power * k;
можна записати
power *= k;
Програма матиме такий вигляд:
package ua.inf.iwanoff.labs.fourth; import java.util.Scanner; public class Powers { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.println("Уведіть n у діапазоні від 1 до 30"); int n = scanner.nextInt(); int power = 1; final int k = 2; if (n < 0 || n > 30) { System.err.println("Неправильне значення n"); } else { for (int i = 0; i <= n; i++) { System.out.printf("2 ^ %2d = %d\n", i, power); power *= k; } } } }
3.2.2 Використання побітових операцій
Більш ефективним буде підхід, який використовує побітову операцію зсуву.
package ua.inf.iwanoff.labs.fourth; import java.util.Scanner; public class PowersOfTwo { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.println("Уведіть n у діапазоні від 0 до 30"); int n = scanner.nextInt(); if (n < 0 || n > 30) { System.err.println("Неправильне значення n"); } else { for (int i = 0; i <= n; i++) { System.out.printf("2 ^ %2d = %d\n", i, 1 << i); } } } }
3.3 Коди символів
Припустимо, необхідно отримати коди символів у заданому діапазоні. Можна реалізувати програму, у якій у циклі виводиться символ і його код:
package ua.inf.iwanoff.labs.fourth; public class Unicodes { public static void main(String[] args) { for (char c = 'А'; c <= 'Я'; c++) { System.out.println(c + " " + (int) c); } } }
З наведеного прикладу видно, що для представлення символів використовується кодування Unicode.
3.4 Сума цифр
Припустимо, необхідно обчислити суму цифр числа. Можна використовувати знаходження залишку від ділення.
package ua.inf.iwanofflabs.fourth; import java.util.Scanner; public class SumOfDigits { public static void main(String[] args) { Scanner s = new Scanner(System.in); int n = s.nextInt(); int sum = 0; while (n > 0) { sum += n % 10; n /= 10; } System.out.println(sum); } }
3.5 Найбільший спільний дільник
Припустимо, необхідно обчислити найбільший спільний дільник. Скористаємось алгоритмом Евкліда, який полягає у послідовному відніманні меншого числа з більшого та заміні більшого числа отриманою різницею. Алгоритм завершується, коли два числа збігатимуться. Програма матиме такий вигляд:
package ua.inf.iwanoff.labs.fourth; import java.util.Scanner; public class GreatestCommonDivisor { static int gcd(int m, int n) { while (m != n) { if (m > n) m -= n; else n -= m; } return m; } public static void main(String[] args) { Scanner s = new Scanner(System.in); int m = s.nextInt(); int n = s.nextInt(); System.out.println(gcd(m, n)); } }
Результат роботи можна використати для обчислення найменшого спільного кратного чисел. Для цього їхній добуток слід поділити на найбільший спільний дільник.
3.6 Рекурсія
Припустимо, необхідно створити рекурсивну функцію обчислення цілого степеня дійсного числа та здійснити тестування для різних значень. Програма матиме такий вигляд:
package ua.inf.iwanoff.labs.fourth; import java.util.Scanner; public class IntPower { static double power(double x, int n) { if (n < 0) { return 1 / power(x, -n); } if (n == 0) { return 1; } return x * power(x, n - 1); } public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("Уведiть x: "); double x = scanner.nextDouble(); System.out.print("Уведiть n: "); int n = scanner.nextInt(); double p = power(x, n); System.out.println("Степiнь: " + p); } }
3.7 Обчислення виразу
Необхідно прочитати з клавіатури x та обчислити y за такою формулою:
де n дорівнює 6. Обчислення виразу слід розмістити в окремій функції. Програма може мати такий вигляд:
package ua.inf.iwanoff.labs.fourth; import java.util.Scanner; public class Formula { public static double f(double x) { final int n = 6; double y; if (x < 0) { y = 0; for (int i = 1; i <= n; i++) { y += (i - x) * (i - x); } } else { y = 1; for (int i = 1; i <= n; i++) { y *= (x + i); } } return y; } public static void main(String[] args) { Scanner s = new Scanner(System.in); double x = s.nextDouble(); double y = f(x); // Виклик функції System.out.println("x = " + x + "\ty = " + y); } }
3.8 Таблиця значень квадратних коренів чисел
Необхідно прочитати з клавіатури значення початку інтервалу, кінця інтервалу, величини кроку, з яким змінюється аргумент та у циклі вивести значення квадратних коренів чисел. Програма може мати такий вигляд:
package ua.inf.iwanoff.labs.fourth; import java.util.Scanner; public class SquareRoots { public static void main(String[] args) { Scanner s = new Scanner(System.in); double from = s.nextDouble(); double to = s.nextDouble(); double step = s.nextDouble(); if (from < 0 || to < 0 || from >= to || step <= 0) { System.out.println("Неправильні дані"); } else { // Основний цикл програми: for (double x = from; x <= to; x += step) { System.out.println("x = " + x + "\t y = " + Math.sqrt(x)); } } } }
У результаті виконання цієї програми на консолі з'являться пари значень x та y.
4 Вправи для контролю
Усі вправи передбачають створення консольного застосунку. Обчислення основного результату здійснити в окремій статичній функції, яка викликається з функції main()
. Введення та виведення здійснювати у функції main()
.
- Увести два дійсних числа. Знайти та вивести середнє арифметичне квадратів чисел.
- Увести два дійсних числа. Знайти та вивести середнє геометричне – квадратний корінь з їхнього добутку. Якщо корінь не можна обчислити, вивести повідомлення про помилку.
- Увести ціле додатне число. Знайти та вивести добуток цифр цього числа.
- Увести ціле додатне число. Знайти та вивести суму парних цифр цього числа.
- Увести ціле додатне число. Знайти та вивести суму квадратів цифр цього числа.
- Увести ціле додатне число. Знайти та вивести суму непарних цифр цього числа.
- Увести ціле додатне число. Знайти та вивести добуток парних цифр цього числа.
- Увести ціле додатне число. Знайти та вивести добуток непарних цифр цього числа.
- Увести ціле додатне число. Перевірити, чи є воно простим. Вивести відповідно "yes" або "no". Число називається простим, якщо у нього рівно два дільника – 1 і визначене число.
- Увести ціле додатне число. Перевірити, чи є воно точним квадратом іншого цілого числа. Вивести знайдене число, або "no" в іншому випадку.
- Увести два цілих додатних числа. Знайти та вивести найменше спільне кратне цих чисел.
- Увести дійсне число та цілий показник степеня (додатний або від'ємний). Обчислити та вивести степінь.
- Увести ціле додатне число n. Знайти та вивести добуток перших n додатних непарних цілих чисел.
- Увести цілі додатні числа n та m, m < n. Знайти та вивести добуток перших n додатних цілих чисел, виключаючи m.
- Увести цілі додатні числа n та m, m < n. Знайти та вивести суму перших n додатних цілих чисел, виключаючи m.
- Увести ціле число – кількість градусів кута. Знайти та вивести величину синуса кута.
- Увести ціле число – кількість градусів кута. Знайти та вивести величину косинуса кута.
- Увести ціле число – кількість градусів n. Знайти та вивести суму синусів кутів з градусами від одиниці до n.
- Створити рекурсивну функцію обчислення суми квадратів перших n чисел.
- Створити рекурсивну функцію обчислення добутку синусів перших n натуральних чисел.
6 Контрольні запитання
- Що таке Java-платформа?
- Чим відрізняється JDK і JRE?
- Що таке віртуальна машина Java?
- Що таке байт-код?
- Що таке Eclіpse?
- Як створити консольний застосунок у середовищі Eclipse?
- Як запустити створену програму на виконання?
- Що таке "конфігурація часу виконання"?
- Які файли містять вихідний код на Java і які містять результат компіляції?
- Коли і як здійснюється компонування Java-програми?
- У чому полягають переваги та недоліки синтаксису мови Java (у порівнянні з С++)?
- Яка різниця між ключовими і зарезервованими словами?
- Чим відрізняються коментарі Javadoc від інших видів коментарів?
- Як створюється вбудована документація?
- Чим відрізняються примітивні типи даних Java від аналогічних типів C++?
- Для чого використовують керуючі послідовності?
- Як здійснюється приведення типів?
- У чому полягають особливості типу
boolean
? - Як привести значення вираз типу
boolean
до цілого типу? - Чим відрізняється префіксна та постфіксна форма операцій інкременту та декременту?
- Чи можна застосовувати операцію & замість && для операндів типу
boolean
? - Чи завжди потрібна мітка при використанні
break
? - Чи можна розмістити декілька пакетів у одному вихідному файлі?
- Чим відрізняються формальні та фактичні параметри функцій?
- Чи можна використовувати інструкцію
return
у тілі функції з типом результатуvoid
? - У чому полягає перевантаження імен функцій?
- Чи можна звертатися до імен з іншого пакета, не використовуючи операції
import
? - У чому є переваги та недоліки статичного імпорту?
- Як виконати скомпільовану програму, не використовуючи середовище Eclipse?