1. Pola klasy: gdzie przechowujemy stan obiektu
Pole — to zmienna deklarowana wewnątrz klasy, ale poza wszystkimi metodami. Pola odpowiadają za to, by każdy obiekt miał swój „stan”. Na przykład, jeśli mamy klasę Person, pola mogą wyglądać tak:
- name — imię osoby
- age — wiek
- balance — saldo na koncie (jeśli akurat tworzymy aplikację bankową)
- isStudent — flaga określająca, czy dana osoba jest studentem
Składnia deklaracji pola
Deklaracja pola przypomina zwykłą zmienną, lecz znajduje się nie wewnątrz metody, a bezpośrednio w klasie:
public class Person {
String name;
int age;
}
Tutaj zadeklarowaliśmy dwa pola: napis name i liczbę całkowitą age. Każde pole będzie należeć do konkretnego obiektu tej klasy. To oznacza, że różne obiekty będą miały własne wartości. Na przykład:
Person p1 = new Person();
p1.name = "Olya";
p1.age = 20;
Person p2 = new Person();
p2.name = "Igor";
p2.age = 25;
Pierwszy obiekt ma imię — „Olya” i wiek — 20, a drugi — „Igor” i 25. Oba powstały z jednej klasy, ale ich pola przechowują różne dane.
Modyfikatory dostępu (public/private)
Pola mogą być publiczne (public) lub prywatne (private). W prawdziwym życiu nie opowiadasz każdemu o swoim saldzie bankowym, prawda? Tak samo w programowaniu często robi się pola private, aby nie można było się do nich odwołać bezpośrednio z innych klas. To część zasady enkapsulacji (więcej — na kolejnych zajęciach).
Przykład:
public class Person {
private String name;
private int age;
}
Na razie nie będziemy komplikować, ale zapamiętaj: jeśli pole jest private, nie da się do niego bezpośrednio odwołać z innej klasy.
2. Metody klasy: jak obiekty „działają”
Metoda — to funkcja, która opisuje zachowanie obiektu. Metody pozwalają obiektowi coś robić: mówić, liczyć, biegać, skakać, wypisywać informacje o sobie i tak dalej.
Składnia deklaracji metody
returnType methodName(parameters) {
// ciało metody
}
Przykład metody, która mówi „Cześć”:
public void sayHello() {
System.out.println("Cześć! Mam na imię " + name);
}
Tutaj:
- public — modyfikator dostępu.
- void — metoda nic nie zwraca (po prostu coś robi).
- sayHello — nazwa metody.
- Wewnątrz metody używamy pola name, aby przywitać użytkownika.
Kolejny przykład: metoda zwracająca wiek
public int getAge() {
return age;
}
Metody mogą zwracać wartości (int, String itd.), a mogą być „nic nie zwracające” — wtedy piszemy void.
3. Konstruktory: jak „rodzą się” obiekty
Konstruktor — to szczególny rodzaj metody wywoływany przy tworzeniu nowego obiektu. Jego zadaniem jest zainicjalizowanie pól obiektu wartościami początkowymi, czyli wypełnienie pustych „kieszonek” obiektu konkretnymi danymi. Na przykład ustawienie imienia i wieku od razu w momencie tworzenia, zamiast zostawiać je puste.
- Nazwa konstruktora zawsze pokrywa się z nazwą klasy.
- Konstruktor nie ma typu zwracanego (nawet void się nie pisze).
- Konstruktory mogą przyjmować parameters (np. imię i wiek) albo nie mieć parametrów.
Przykład konstruktora
public class Person {
String name;
int age;
// Konstruktor z dwoma parametrami
public Person(String name, int age) {
this.name = name; // this.name — pole obiektu, name — parametr konstruktora
this.age = age;
}
}
Być może zastanawiasz się, czym jest this. Otóż słowo kluczowe this to odwołanie do bieżącego obiektu — od środka. Używamy go, aby odróżnić pole klasy od parametru o tej samej nazwie. Bez this kompilator by się pogubił, co dokładnie chcemy zainicjalizować.
Konstruktor domyślny
Jeśli nie zadeklarujesz żadnego konstruktora, kompilator Java automatycznie doda pusty konstruktor bez parametrów. Wygląda tak:
public Person() {
// nic nie robi, ale pozwala utworzyć obiekt bez parametrów
}
UWAGA! Jeśli zadeklarujesz choć jeden własny konstruktor (np. z parametrami), to konstruktor domyślny nie będzie już tworzony automatycznie! Jeśli jest potrzebny — napisz go jawnie.
4. Przykład pełnej klasy
Zbierzmy wszystko razem: pola, metody, konstruktor.
public class Person {
String name;
int age;
// Konstruktor
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// Metoda: powiedzieć cześć
public void sayHello() {
System.out.println("Cześć! Mam na imię " + name + ", mam " + age + " lat.");
}
// Metoda: zwiększyć wiek o 1
public void haveBirthday() {
age = age + 1;
System.out.println("Hura! Mam teraz " + age + " lat!");
}
}
Jak tego użyć w programie?
public class Main {
public static void main(String[] args) {
Person vasya = new Person("Vasya", 18);
vasya.sayHello(); // Cześć! Mam na imię Vasya, mam 18 lat.
vasya.haveBirthday(); // Hura! Mam teraz 19 lat!
}
}
5. Praktyka: rozwijamy twoją aplikację
Załóżmy, że tworzysz prostą aplikację do ewidencji użytkowników. Na poprzednich zajęciach pracowaliśmy tylko ze zmiennymi i metodami wewnątrz main. Teraz utworzymy własną klasę User z polami, metodami i konstruktorem.
public class User {
String username;
int score;
// Konstruktor
public User(String username, int score) {
this.username = username;
this.score = score;
}
// Metoda: wypisać informacje o użytkowniku
public void printInfo() {
System.out.println("Nazwa użytkownika: " + username + ", punkty: " + score);
}
// Metoda: zwiększyć liczbę punktów
public void addScore(int points) {
score += points;
System.out.println(username + " otrzymał " + points + " punktów! Teraz ma " + score + " punktów.");
}
}
Użycie:
public class Main {
public static void main(String[] args) {
User alice = new User("Alice", 10);
User bob = new User("Bob", 5);
alice.printInfo(); // Nazwa użytkownika: Alice, punkty: 10
bob.printInfo(); // Nazwa użytkownika: Bob, punkty: 5
alice.addScore(7); // Alice otrzymał 7 punktów! Teraz ma 17 punktów.
bob.addScore(3); // Bob otrzymał 3 punkty! Teraz ma 8 punktów.
}
}
Zwróć uwagę: każdy obiekt ma własne pola, a zmiany jednego obiektu nie wpływają na inny.
6. Krótko o modyfikatorach dostępu
W naszych przykładach pola były publiczne (String name;). W praktyce często robi się pola private, aby nie można było ich przypadkowo (albo celowo) zmienić z innej klasy. Szczegóły pojawią się w temacie enkapsulacji, a oto przykład:
public class User {
private String username;
private int score;
public User(String username, int score) {
this.username = username;
this.score = score;
}
public void printInfo() {
System.out.println("Nazwa użytkownika: " + username + ", punkty: " + score);
}
public void addScore(int points) {
score += points;
}
}
Teraz jeśli ktoś spróbuje napisać alice.score = 100500; poza klasą — kompilator powie „nie można!”.
7. Typowe błędy przy pracy z polami, metodami i konstruktorami
Błąd nr 1: Nie zainicjalizowane pola.
Jeśli nie nadajesz polom wartości, otrzymują wartości domyślne: liczby — 0, boolean — false, referencje (np. String) — null. Jeśli zapomnisz zainicjalizować pole, możesz uzyskać nieoczekiwany rezultat, a nawet NullPointerException przy próbie zrobienia z nim czegokolwiek.
Błąd nr 2: Mylenie parametrów i pól.
W konstruktorze początkujący często piszą po prostu name = name; — to nie inicjalizuje pola, a jedynie przypisuje parametr samemu sobie. Zawsze używaj this.name = name!
Błąd nr 3: Brak konstruktora domyślnego.
Jeśli zadeklarujesz konstruktor z parametrami, ale zapomnisz jawnie dodać pusty konstruktor, to new Person() już nie zadziała.
Błąd nr 4: Jednakowe nazwy metod i klas.
W Java nazwa konstruktora musi pokrywać się z nazwą klasy, ale w przypadku metod — nie powinna. Czasem przez pomyłkę metoda ma taką samą nazwę jak klasa i kompilator się buntuje.
Błąd nr 5: Zapomniane modyfikatory dostępu.
Jeśli zrobisz pola public, można je zmieniać gdziekolwiek — to niebezpieczne w dużych programach. Lepiej od razu przyzwyczaić się do private i używać metod do dostępu.
GO TO FULL VERSION