Първа програма на Java
Създаване на проект в IntelliJ IDEA
След стартиране на средата за разработка IntelliJ IDEA се избира опцията New Project, след което се отворя прозорец за конфигурация на новия проект:
Попълват се следните основни настройки:
- Name - име на проекта; в примера от фигурата е JavaBsics
- Location - директория, в която ще бъде съхранен проектът; в горният пример е Desktop
- Build System - IntelliJ;
- JDK - версията на Java, която ще бъде използвана от проекта; в примера от фигурата е OpenJDK-17
Структура на проекта
След създаването на проекта IntelliJ IDEA генерира неговата начална структура.
Основните елементи са:
- Проект - основната директория;
- src - директория, съдържаща изходния код;
- out - директория, съдържаща компилираните .class файлове;
- External Libraries - библиотеките, използвани от проекта.
Забележка: Директорията out се създава автоматично след първото успешно компилиране на проекта.
Организация чрез пакети
Преди създаването на класове е препоръчително първо да бъде създаден пакет.
Пакетите служат за:
- логическо групиране на класове;
- избягване на конфликти между имената на класовете;
- организиране на структурата на пакета.
За създаване на нов пакет върху директорията src от контекстното меню се избира:
New -> Package
В рамките на курса ще бъде използвана следната структура на основния пакет:
bg.tu_varna.sit.<група>.<факултетен_номер>.task<номер_на_задача>
Забележка: Предварително дефинираните конвенции за именуване и организация на проектите позволяват различни инструменти автоматично да анализират, компилират, тестват и оценяват програмния код. Поради тази причина и в рамките на курса се използва единна структура на пакетите.
Използване на import
Ключовата дума import се използва, когато в даден файл трябва да се използва клас от друг пакет. Така пълното име на класа не се изписва при всяка употреба.
import java.util.Scanner;
След този запис класът Scanner може да бъде използван само чрез краткото си име.
Scanner scanner = new Scanner(System.in);
Декларациите import се записват след декларацията package и преди декларацията на класа.
package bg.tu_varna.example;
import java.util.Scanner;
public class Application {
}
Създаване на първи клас
След създаването на пакета се създава първия Java клас, като от контекстното меню на пакета се избира New -> Java Class.
Името на класа трябва да бъде смислено и да описва предназначението му. В примерите от курса класът, съдържащ метода main, ще бъде именуван Application.
Методът main
Изпълнението на всяко Java приложение започва от метода main:
Този метод представлява входната точка на Java приложението. При стартиране на програмата JVM започва изпълнението именно от този метод. В примерите от курса той винаги ще бъде дефиниран в класа Application. Това следва широко използваната практика в Java екосистемата, при която класът, преставляващ входната точка на приложението, се именува по този начин.
Стартирането на методът main може да стане по няколко начина, като фигурата по-долу показва част от тези възможности:
Изборът на която и да е от посочените опции ще стартира изпълнението на програмата. Резултатът от конкретния код ще бъде извеждане на конзолата на съобщението (обикновено се отваря в прозорец отдолу):
This is an example
Видове грешки
Грешка в програма е състояние, при което кодът не се компилира, прекъсва изпълнението си или дава резултат, различен от очаквания. Откриването на грешки изисква последователно наблюдение на изпълнението, стойностите на променливите и пътя, по който програмата преминава през условни оператори, цикли и методи.
Синтактична грешка възниква, когато кодът не спазва правилата на езика Java. Такава грешка се открива от компилатора преди стартиране на програмата.
int number = 10
System.out.println(number);
В примера липсва ; след първата инструкция. Програмата не може да бъде компилирана.
Грешка по време на изпълнение възниква след успешно компилиране, когато програмата достигне до операция, която не може да бъде изпълнена.
int result = 10 / 0;
В примера делението на нула води до прекъсване на програмата по време на изпълнение.
Логическа грешка възниква, когато програмата се компилира и изпълнява, но резултатът е неправилен.
int width = 5;
int height = 10;
int perimeter = width * height;
Кодът се изпълнява, но изчислява лице, а не периметър. Такава грешка се открива чрез проверка на стойностите и очаквания резултат.
Debug режим
Debug режимът позволява програмата да се изпълнява контролирано. Вместо да се стартира цялата програма наведнъж, изпълнението може да бъде спирано на избрани редове. Така се наблюдават стойностите на променливите и редът на изпълнение.
Точка на прекъсване се поставя върху ред от програмата. Когато изпълнението достигне този ред, програмата спира временно. След спирането може да се провери текущото състояние на програмата.
int first = 10;
int second = 20;
int sum = first + second;
System.out.println(sum);
Ако точка на прекъсване се постави на реда със sum, може да се види какви стойности имат first и second преди изчислението.
Точки на прекъсване
Точка на прекъсване е маркер върху конкретен ред от програмата. Когато изпълнението достигне този ред в debug режим, програмата спира временно преди изпълнението на инструкцията.
Точка на прекъсване се използва, когато трябва да се провери:
- дали даден ред от програмата се достига;
- какви са текущите стойности на променливите;
- кой клон на условен оператор се изпълнява;
- колко пъти се изпълнява даден цикъл.
int total = 0;
for (int i = 1; i <= 5; i++) {
total = total + i;
}
Ако точка на прекъсване се постави в тялото на цикъла, може да се наблюдава как стойностите на i и total се променят при всяка итерация.
Постъпково изпълнение
Постъпковото изпълнение позволява преминаване през програмата ред по ред.
Step Over изпълнява текущия ред и преминава към следващия. Ако текущият ред съдържа извикване на метод, методът се изпълнява без влизане в неговото тяло.
Step Into влиза в извиквания метод. Използва се, когато трябва да се проследи как работи методът отвътре.
Step Out завършва текущия метод и връща изпълнението към мястото, от което методът е извикан.
Пауза, възобновяване и спиране на debugger
Debug изпълнението може да бъде управлявано чрез команди за пауза, възобновяване и спиране.
Pause спира временно изпълняваната програма. Използва се, когато програмата работи дълго или е попаднала в цикъл и трябва да се провери текущото място на изпълнение.
Resume Program продължава изпълнението след спиране на точка на прекъсване. Програмата се изпълнява до следващата точка на прекъсване или до края си.
Stop прекратява debug сесията. След прекратяване програмата вече не се изпълнява под контрола на debugger.
Прозорец за отстраняване на грешки
Прозорецът за отстраняване на грешки показва информация за текущото състояние на програмата, когато изпълнението е спряло. В него се наблюдават текущият метод, стекът на извикванията, стойностите на променливите и изходът на програмата.
| Част | Предназначение |
|---|---|
Debugger | Показва управлението на debug сесията и текущото място на изпълнение |
Console | Показва стандартния изход и съобщенията от програмата |
Frames | Показва последователността от извикани методи до текущия момент |
Variables | Показва локални променливи, параметри и полета на достъпните обекти |
Watches | Позволява наблюдение на избрани изрази по време на debug изпълнение |
Стекът във Frames е полезен, когато един метод е извикан от друг метод. Чрез него може да се проследи пътят, по който изпълнението е достигнало до текущия ред.
Прозорец за променливи
При спиране на програмата debugger показва текущите стойности на локалните променливи, параметрите и обектите. Ако дадена променлива сочи към обект, могат да се разгледат и полетата на този обект.
class Student {
private String name;
private int facultyNumber;
public Student(String name, int facultyNumber) {
this.name = name;
this.facultyNumber = facultyNumber;
}
}
При спиране след създаване на обект от Student може да се провери дали полетата name и facultyNumber са инициализирани правилно.
Оценяване на изрази
Оценяването на изрази позволява да се изчисли Java израз по време на debug изпълнение. Изразът се оценява с текущите стойности на променливите.
int price = 50;
int quantity = 3;
int discount = 10;
По време на debug изпълнение може да се оцени израз:
price * quantity - discount
Резултатът е 140. Така може да се провери дали формула, условие или метод връща очакваната стойност.
Quick Evaluate Expression
Quick Evaluate Expression се използва за бърза проверка на избран израз по време на debug изпълнение. Опцията е налична, когато програмата е спряла на точка на прекъсване.
int first = 10;
int second = 20;
int result = first + second;
Ако изпълнението е спряло преди или след изчисляването на result, може да се избере изразът first + second и да се провери неговата стойност. В IntelliJ IDEA това действие може да се изпълни чрез Run -> Debugging Actions -> Quick Evaluate Expression, чрез клавишна комбинация Ctrl+Alt+F8 или чрез Alt и кликване върху избрания израз.
Evaluate Expression
Evaluate Expression позволява оценяване на израз или кратък кодов фрагмент в текущия контекст на изпълнение. Тази операция е по-гъвкава от бързото оценяване, защото може да се въведе нов израз, който не е директно избран от редактора.
int price = 50;
int quantity = 3;
int discount = 10;
При спиране на програмата може да се оцени изразът:
price * quantity - discount
Може да се оцени и условие:
price * quantity > 100
В IntelliJ IDEA действието се отваря чрез Run -> Debugging Actions -> Evaluate Expression или с клавишна комбинация Alt+F8. Оценяването се извършва спрямо текущия стеков кадър, затова могат да се използват само променливи и обекти, които са достъпни на мястото, където програмата е спряла.
Оценяване на условие
Оценяването на изрази е полезно при условни оператори.
int age = 17;
if (age >= 18) {
System.out.println("Adult");
} else {
System.out.println("Minor");
}
Ако изпълнението спре преди if, може да се оцени изразът age >= 18. Резултатът показва кой клон на условието ще бъде изпълнен.
Аргументи към main
Методът main може да получава аргументи чрез масива String[] args.
public class Application {
public static void main(String[] args) {
System.out.println(args[0]);
}
}
Ако програмата се стартира без аргументи, достъпът до args[0] води до грешка по време на изпълнение. Debug режимът позволява да се провери дължината на масива чрез args.length и да се установи причината за грешката.