Wykład 3
w Javie argumenty są zawsze przekazywane przez wartość.
Sama deklaracja daje “niezainicjowaną tablicę”
Tablica pusta w Javie to tablica, która ma rozmiar zero. Innymi słowy, nie może przechowywać żadnych elementów, ale to wciąż jest prawidłowy obiekt tablicy.
Jeśli tablica jest równa null
, oznacza to, że nie odnosi się do żadnego obiektu w pamięci. Jest to specjalna wartość, która reprezentuje, że zmienna tablicy nie ma aktualnie przypisanego obiektu.
ArrayList
ArrayList
to jedna z najczęściej używanych implementacji interfejsu List
. Jest to dynamicznie rozszerzalna tablica, która może zmieniać swój rozmiar w miarę dodawania i usuwania elementów. Wewnętrznie ArrayList
używa tablicy do przechowywania elementów.
Własności:
Wewnętrzna struktura danych: Jak wspomniano wcześniej, ArrayList
wewnętrznie używa tablicy do przechowywania elementów. Gdy lista staje się pełna i potrzeba dodać kolejny element, Java tworzy większą tablicę i kopiuje elementy starej tablicy do nowej.
Rozmiar vs. Pojemność:
ArrayList
może zmieniać swój rozmiar w miarę potrzeb, co czyni ją bardziej elastyczną niż zwykłe tablice.null
.LinkedList
z powodu dodatkowej pojemności rezerwowej.Bezpieczeństwo wątkowe: Standardowa implementacja ArrayList
nie jest synchronizowana, co oznacza, że nie jest bezpieczna do użytku w środowiskach wielowątkowych bez odpowiedniej synchronizacji. Jeśli potrzebujesz wersji synchronizowanej, możesz użyć Collections.synchronizedList()
.
Pamięć: Jeśli znasz ostateczny rozmiar listy, warto zainicjalizować ArrayList
z odpowiednią pojemnością początkową, aby uniknąć wielokrotnego rozszerzania wewnętrznej tablicy.
Okej, przyjrzyjmy się niektórym z najczęściej używanych metod i właściwości klasy ArrayList
w Javie:
add(E element)
:
add(int index, E element)
:
get(int index)
:
remove(int index)
:
remove(Object o)
:
size()
:
isEmpty()
:
clear()
:
contains(Object o)
:
indexOf(Object o)
:
set(int index, E element)
:
toArray()
:
Klasy takie jak ArrayList
są generycznymi klasami kontenerowymi, które przechowują obiekty, a nie typy proste. Dlatego nie możemy bezpośrednio użyć int
lub double
jako typu elementu dla ArrayList
.
Aby rozwiązać ten problem, Java dostarcza klasy opakowujące (wrapper classes) dla wszystkich typów prostych. Dla int
mamy Integer
, dla double
mamy Double
itd.
Dzięki autoboxingowi (automatyczne konwersje między typami prostymi a ich klasami opakowującymi) korzystanie z tych klas opakowujących jest stosunkowo proste i wygodne.
Dla int
:
Dla double
:
Domyślne wyświetlanie zawartości ArrayList
jest dość proste dzięki nadpisanemu przez klasę ArrayList
metodzie toString()
. Gdy wywołasz metodę System.out.println
na obiekcie ArrayList
, Java automatycznie wywołuje metodę toString()
klasy ArrayList
.
Niezainicjowana lista tablicowa:
ArrayList
, ale nie przypisującej jej do żadnego obiektu.Pusta lista tablicowa:
ArrayList
został zainicjowany, ale nie zawiera żadnych elementów.ArrayList
i możesz wykonywać na nim operacje, takie jak dodawanie i usuwanie elementów.null
:
ArrayList
jest jawnie ustawiona na wartość null
lub domyślnie jest ustawiona na null
i nie została zainicjowana później.null
, spowoduje błąd w czasie wykonywania zwanym NullPointerException
.import java.util.ArrayList;
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
ArrayList<String> lt1 = new ArrayList<>();
ArrayList<String> lt2 = new ArrayList<>(10); // Pojemność początkowa 10
ArrayList<Integer> lt3 = new ArrayList<>(){{
add(5);
add(-4);
add(3);
}};
}
}
Inicjalizacja:
Używanie metody System.identityHashCode
nie jest zalecane!
Niezmienność (Immutability):
String
są niezmienne. Oznacza to, że raz utworzony łańcuch znaków nie może być zmieniony. Wszelkie operacje modyfikujące zawartość łańcucha (np. dodawanie, usuwanie znaków) skutkują stworzeniem nowego obiektu String
.Konkatenacja:
+
:Porównywanie:
equals()
zamiast operatora ==
:Pamięć:
new
.Zmienne łańcuchowe:
StringBuilder
i StringBuffer
. Są one szczególnie przydatne w sytuacjach, gdzie zachodzi wiele modyfikacji łańcucha, ponieważ operują one w miejscu (in-place) i są zwykle szybsze niż tworzenie wielu obiektów String
.null
Wartość:
""
): To faktyczny obiekt klasy String
, który ma wartość, ale ta wartość jest pusta. Inaczej mówiąc, jest to łańcuch, który nie zawiera żadnych znaków.null
: To specjalna wartość, która oznacza, że zmienna nie wskazuje na żaden obiekt. Dla zmiennej typu String
, jeśli jest ona ustawiona na null
, nie wskazuje ona na żaden łańcuch (pusty czy inny).Długość:
""
): Jego długość wynosi 0. Można to sprawdzić używając metody length()
: "".length()
zwróci 0.null
: Zmienna o wartości null
nie posiada metod ani atrybutów. Próba wywołania metody, np. null.length()
, spowoduje wyjątek NullPointerException
.Operacje:
""
): Możesz wykonywać na nim różne operacje, takie jak konkatenacja czy wywoływanie innych metod klasy String
.null
: Nie możesz wykonywać na nim żadnych operacji. Każda próba dostępu do metody lub atrybutu na zmiennej o wartości null
spowoduje NullPointerException
.Porównywanie:
Możesz porównać zarówno łańcuch pusty, jak i null
z innymi łańcuchami. Ale musisz być ostrożny z null
, ponieważ:
Zastosowania:
""
): Często używany do inicjowania łańcuchów bez konkretnej wartości lub do wskazania, że łańcuch powinien być “czysty” lub “bez wartości”, ale nadal istnieje.null
: Wskazuje, że zmienna nie odnosi się do żadnego obiektu. Jest używane w wielu przypadkach, np. gdy wartość nie jest jeszcze znana lub nie została ustawiona.length()
:
Zwraca liczbę znaków w łańcuchu.
charAt(int index)
:
Zwraca znak na określonej pozycji w łańcuchu.
substring(int beginIndex, int endIndex)
:
Zwraca nowy łańcuch zawierający znaki z oryginalnego łańcucha od beginIndex
(włącznie) do endIndex
(wyłącznie).
indexOf(String str)
i lastIndexOf(String str)
:
Zwracają indeks pierwszego/ostatniego wystąpienia podciągu w łańcuchu. Jeśli podciąg nie jest znaleziony, zwraca -1.
equals(Object obj)
:
Porównuje zawartość tego łańcucha z zawartością innego obiektu. Zwraca true
, jeśli są równe.
equalsIgnoreCase(String anotherString)
:
Porównuje łańcuchy bez uwzględniania wielkości liter.
startsWith(String prefix)
i endsWith(String suffix)
:
Sprawdzają, czy łańcuch zaczyna się lub kończy danym ciągiem znaków.
replace(char oldChar, char newChar)
lub replace(CharSequence target, CharSequence replacement)
:
Zwraca nowy łańcuch, w którym wszystkie wystąpienia oldChar
lub target
są zastąpione przez newChar
lub replacement
.
trim()
:
Zwraca kopię łańcucha z usuniętymi białymi znakami na początku i końcu.
toLowerCase()
i toUpperCase()
:
Zmieniają wielkość liter w łańcuchu.
split(String regex)
:
Dzieli łańcuch według podanego wyrażenia regularnego.
isEmpty()
:
Sprawdza, czy łańcuch jest pusty (długość wynosi 0).
valueOf()
(statyczna metoda):
Konwertuje różne typy danych (np. int, char) na łańcuchy.
String
:
String
są niemutowalne, co oznacza, że po ich utworzeniu nie można ich zmienić. Każda operacja, która wydaje się modyfikować łańcuch (np. konkatenacja), faktycznie tworzy nowy obiekt String
.StringBuilder
:
StringBuilder
są mutowalne. Można dodawać, usuwać i modyfikować zawartość obiektu bez tworzenia nowych obiektów.String
w operacjach modyfikujących, szczególnie w intensywnych operacjach, takich jak budowanie łańcuchów w pętlach.StringBuilder
jest zwykle lepszym wyborem niż StringBuffer
.Często używane metody:
append():
Dodaje wartość do końca obecnej zawartości StringBuilder
.
Jest przeciążona, by obsłużyć różne typy danych: String
, char
, int
, long
, float
, double
itp.
Przykład:
insert():
Wstawia wartość w określonej pozycji w StringBuilder
.
Przykład:
delete() i deleteCharAt():
delete(int start, int end)
usuwa podciąg znaków od indeksu start
do indeksu end - 1
.
deleteCharAt(int index)
usuwa znak w określonym indeksie.
Przykład:
replace():
Zamienia podciąg znaków w określonym zakresie na inny ciąg znaków.
Przykład:
toString():
Konwertuje StringBuilder
na String
.
Przykład:
length():
Zwraca liczbę znaków w StringBuilder
.
Przykład:
setLength():
Ustawia długość StringBuilder
. Jeśli nowa długość jest krótsza niż obecna, ciąg zostanie obcięty. Jeśli jest dłuższy, dodane zostaną znaki o wartości \u0000
.
Przykład:
charAt(), setCharAt():
charAt(int index)
zwraca znak w określonym indeksie.
setCharAt(int index, char ch)
ustawia znak w określonym indeksie.
Przykład:
reverse():
Odwraca kolejność znaków w StringBuilder
.
Przykład:
StringBuffer
:
StringBuilder
, obiekty StringBuffer
są mutowalne.StringBuilder
, ale operacje są synchronizowane.StringBuffer
może być odpowiednim wyborem.Metody dla StringBuffer
są w większości analogiczne jak dla StringBuilder
.
https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/Character.html
Klasa w programowaniu obiektowym w języku Java to podstawowy koncept i “struktura”formuła”, która pozwala na tworzenie obiektów.
Blueprint: Klasa jest jak “projekt” lub szablon, który opisuje, jakie zmienne (stany) i metody (zachowania) powinien posiadać obiekt tej klasy.
Enkapsulacja (hermatyzacja): Klasa kapsułkuje dane dla obiektu i funkcje, które operują na tych danych. To pozwala na ukrycie szczegółów implementacji i eksponowanie tylko niezbędnych interfejsów.
Konstruktor: Klasa może posiadać specjalne metody nazywane konstruktorami, które są używane do inicjalizacji obiektu podczas jego tworzenia.
Dziedziczenia: Klasa może dziedziczyć zmienne i metody z innej klasy. Dziedziczenie pozwala na tworzenie nowej klasy na bazie już istniejącej, co ułatwia ponowne wykorzystanie kodu.
Modyfikatory: Klasy mogą być opatrzone różnymi modyfikatorami, które decydują o dostępie do klasy oraz jej składników.
Zmienne instancyjne: Wewnątrz klasy można zdefiniować zmienne, które będą przechowywać stan obiektu.
Metody: Metody to funkcje zdefiniowane w klasie, które operują na zmiennych instancji i definiują zachowanie obiektu.
Klasy wewnętrzne: Java pozwala na definiowanie klas wewnątrz innych klas, co nazywane jest klasami wewnętrznymi.
Obiekt to podstawowy byt w programowaniu obiektowym. Jest to konkretna instancja klasy, która jest jak “projekt” lub “szablon”. Obiekty stanowią podstawę działania wielu aplikacji i systemów. Aby zrozumieć obiekty, warto je podzielić na trzy główne aspekty: stan, zachowanie i tożsamość.
Samochod
, stan tego obiektu mógłby być reprezentowany przez takie zmienne jak marka
, model
, rokProdukcji
, kolor
itp.Samochod
, przykładowe zachowania mogłyby obejmować przyspiesz()
, zatrzymaj()
, skręćWLewo()
itp.Samochod
mogą mieć taki sam stan (takie same marki, modele, kolory itp.), każdy z nich będzie miał unikalny adres pamięci, dzięki czemu można je odróżnić.Samochod
, OsobaKontaktowa
.KontoBankowe
zamiast PrzetwarzanieTransakcji
.public
, private
i protected
.private
) aby chronić je przed niepożądanym dostępem z zewnątrz.public
.get
lub set
, a następnie nazwa zmiennej z wielkiej litery, np. getImie()
lub setImie()
./** ... */
) do dokumentowania klas, zmiennych i metod. Dzięki temu inne osoby korzystające z Twojego kodu będą miały łatwy dostęp do opisu funkcjonalności.https://www.oracle.com/java/technologies/javase/codeconventions-fileorganization.html
https://google.github.io/styleguide/javaguide.html#s3.4.2-class-member-ordering
public static final
zmienne).public class Car {
// 1. Deklaracje członków klasy
// a. Stałe
public static final int MAX_SPEED = 200;
// b. Zmienne statyczne
private static int totalCarsProduced;
// c. Zmienne instancji
private String make;
private String model;
private int year;
private int speed;
// 2. Konstruktory
public Car(String make, String model, int year) {
this.make = make;
this.model = model;
this.year = year;
this.speed = 0;
totalCarsProduced++;
}
// 3. Metody
// a. Metody fabrykujące (jeśli by były potrzebne, dla demonstracji)
public static Car createVintageCar(String make, String model) {
return new Car(make, model, 1960);
}
// b. Metody dostępowe (gettery i settery)
public String getMake() {
return make;
}
public void setMake(String make) {
this.make = make;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public int getSpeed() {
return speed;
}
// c. Metody publiczne
public void accelerate() {
if (speed < MAX_SPEED) {
speed += 10;
}
}
public void decelerate() {
if (speed > 0) {
speed -= 10;
}
}
// d. Metody chronione (dla demonstracji, w tym przypadku mogą nie mieć sensu)
protected void resetCar() {
speed = 0;
}
// e. Metody prywatne
private void updateTotalCars() {
totalCarsProduced++;
}
// 4. Wewnętrzne klasy (dla demonstracji)
private class Engine {
private int horsepower;
private String type;
Engine(int horsepower, String type) {
this.horsepower = horsepower;
this.type = type;
}
public int getHorsepower() {
return horsepower;
}
public String getType() {
return type;
}
}
}
W Javie, jeśli klasa nie ma zdefiniowanego żadnego konstruktora, kompilator dostarcza domyślny konstruktor bezargumentowy (nazywany również konstruktorem domyślnym). Ten konstruktor nie ma żadnego ciała i służy wyłącznie do tworzenia obiektów.
Jeśli jednak zdefiniujesz choć jeden konstruktor dla klasy, kompilator już nie dostarcza domyślnego konstruktora. W takim przypadku, jeśli chcesz mieć konstruktor bezargumentowy, musisz go jawnie zdefiniować.
public class Dog {
// Zmienne instancji
private String name;
private String breed;
// Metody
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getBreed() {
return breed;
}
public void setBreed(String breed) {
this.breed = breed;
}
}
// Główna klasa z metodą main do demonstracji
public class TestDog {
public static void main(String[] args) {
// Tworzenie obiektu klasy Dog przy użyciu domyślnego konstruktora
Dog myDog = new Dog();
// Ustawianie wartości za pomocą setterów, ponieważ nie mamy zdefiniowanego konstruktora z argumentami
myDog.setName("Rex");
myDog.setBreed("Golden Retriever");
// Wydrukowanie wartości
System.out.println("Name: " + myDog.getName());
System.out.println("Breed: " + myDog.getBreed());
}
}
new
Operator new
w Javie odgrywa kluczową rolę w tworzeniu nowych obiektów i jest nieodłącznym elementem programowania obiektowego w tym języku.
new
, system przydziela pamięć dla nowego obiektu w stercie (ang. heap). Sterta jest obszarem pamięci przeznaczonym do alokacji pamięci dla obiektów w czasie działania programu.new
nie tylko alokuje pamięć, ale również inicjuje obiekt poprzez wywołanie odpowiedniego konstruktora klasy.new
zwraca referencję do tego obiektu. Referencję tę można przypisać do zmiennej, która jest zmienną referencyjną odpowiedniego typu.new
, można od razu użyć konstruktora klasy, aby zainicjować obiekt. Na przykład: new Dog("Rex")
używa konstruktora klasy Dog
, który przyjmuje jeden argument typu String
.new
jest również używany do tworzenia tablic w Javie. Na przykład: new int[5]
tworzy tablicę pięciu elementów typu int
.Operator kropki (wyboru składowej) .
jest jednym z najczęściej używanych operatorów i ma wiele zastosowań w kontekście dostępu do składowych klasy lub obiektu.
Zastosowania:
Operator kropki pozwala na dostęp do pól (zmiennych instancji) oraz metod obiektu. Jeśli pole lub metoda są oznaczone jako public
, można do nich bezpośrednio odwołać się za pomocą operatora kropki.
Można użyć operatora kropki do dostępu do statycznych składowych klasy (czyli tych, które są oznaczone słowem kluczowym static
). W tym przypadku odnosimy się bezpośrednio do klasy, a nie do instancji klasy.
Operator kropki jest używany do odwoływania się do klas wewnątrz pakietów.
W sytuacjach, gdy chcemy się odwołać do konkretnej klasy lub składowej w ramach określonego pakietu, używamy operatora kropki.
W kontekście dziedziczenia, jeśli podklasa chce się odwołać do składowej klasy bazowej, która została przesłonięta w podklasie, można użyć słowa kluczowego super
w połączeniu z operatorem kropki.
Jeśli klasa ma zagnieżdżoną klasę wewnętrzną, można odwołać się do niej za pomocą operatora kropki.
Bloki inicjujące w Javie to specjalne bloki kodu, które są wykonywane podczas tworzenia obiektu. Służą one do inicjalizacji zmiennych instancji oraz do wykonywania pewnych operacji przed wywołaniem konstruktora klasy.
Java oferuje dwa rodzaje bloków inicjujących:
Wartości domyślne:
Jeśli zmiennej instancji nie przypiszemy wartości, Java automatycznie przypisuje jej wartość domyślną w zależności od typu zmiennej:
int
, float
, double
): 0
boolean
: false
char
: \u0000
(null)null
public class TestSample {
public static void main(String[] args) {
System.out.println("Main method started");
// Tworzenie obiektu klasy Sample
Sample sample = new Sample();
System.out.println("Instance Variable: " + sample.instanceVar);
}
}
class Sample {
// Zmienna instancji
public int instanceVar;
// Konstruktor
public Sample() {
System.out.println("Constructor executed");
}
// Blok inicjujący instancji
{
instanceVar = 10;
System.out.println("Instance block executed");
}
}
null
Wyjątek NullPointerException
(NPE) pojawia się, gdy program próbuje odwołać się do obiektu lub wywołać metodę na referencji, która jest null
.
Podstawowe zasady (na ten moment)
Inicjalizuj zmienne: - Gdy to możliwe, inicjalizuj zmienne w momencie ich deklaracji. - Unikaj pozostawiania zmiennych referencyjnych bez wartości (niewypełnionych).
Sprawdzaj obiekty przed użyciem: - Zawsze sprawdzaj, czy referencja nie jest null
, zanim użyjesz jej do wywołania metody lub dostępu do pola.
Objects.requireNonNull(T obj)
:
obj
nie jest null
.null
, metoda rzuci wyjątek NullPointerException
.null
, zostanie zwrócony bez zmian.Objects.requireNonNull(T obj, String message)
.null
.Objects.requireNonNullElse(T obj, T defaultObj)
:
obj
nie jest null
.obj
jest null
, zwraca defaultObj
jako wartość domyślną.obj
nie jest null
, zwraca obj
.null
.Modyfikatory dostępu w Javie określają zakres widoczności i dostępności składowych klasy (tj. pól, metod, konstruktorów, itp.). Istnieje cztery główne modyfikatory dostępu:
private
:
private
jest dostępna wyłącznie w obrębie klasy, w której została zdefiniowana.default
(brak modyfikatora):
protected
:
protected
jest dostępna w obrębie jej klasy, w obrębie wszystkich klas w tym samym pakiecie, a także w subklasach (nawet jeśli są w innym pakiecie).public
, ale mniej niż private
i default
.public
:
public
jest dostępna z każdej klasy, niezależnie od pakietu.