Java 2 Flashcards
Jaki jest związek między interfejsem a klasą abstrakcyjną w Javie?
Odpowiedź: Interfejsy definiują zestaw abstrakcyjnych metod, które implementujące klasy muszą zaimplementować, podczas gdy klasy abstrakcyjne mogą zawierać zarówno metody abstrakcyjne, jak i konkretne metody.
Co to jest serializacja i deserializacja w Javie?
Odpowiedź: Serializacja to proces przekształcania obiektu Javy na strumień bajtów, podczas gdy deserializacja to proces odtwarzania obiektu z tego strumienia bajtów.
Jakie są różnice między HashMap a HashTable w Javie?
HashMap
i HashTable
to dwie struktury danych w Javie, które przechowują dane w formie par klucz-wartość. Mimo że obie implementują interfejs Map
, istnieją między nimi istotne różnice:
-
Synchronizacja i Wielowątkowość:
-
HashMap nie jest synchronizowana, co oznacza, że nie jest bezpieczna w środowisku wielowątkowym bez zewnętrznej synchronizacji. Jej metody nie są
synchronized
. -
HashTable jest synchronizowana, co oznacza, że jej metody są
synchronized
i jest bezpieczna w użyciu w środowisku wielowątkowym. Jednak synchronizacja wiąże się z kosztem wydajności.
-
HashMap nie jest synchronizowana, co oznacza, że nie jest bezpieczna w środowisku wielowątkowym bez zewnętrznej synchronizacji. Jej metody nie są
-
Null Values i Null Keys:
-
HashMap pozwala na jedną wartość
null
jako klucz i dowolną liczbę wartościnull
. -
HashTable nie pozwala na żadne klucze
null
ani wartościnull
.
-
HashMap pozwala na jedną wartość
-
Iterator i Enumerator:
-
HashMap oferuje iterator, który jest szybki, ale nie gwarantuje kolejności elementów. Iterator w HashMap jest niezawodny (fail-fast), co oznacza, że zgłosi
ConcurrentModificationException
przy próbie modyfikacji mapy podczas iteracji. - HashTable oferuje enumerator i iterator. Enumerator nie jest fail-fast.
-
HashMap oferuje iterator, który jest szybki, ale nie gwarantuje kolejności elementów. Iterator w HashMap jest niezawodny (fail-fast), co oznacza, że zgłosi
-
Wydajność:
- HashMap zazwyczaj oferuje lepszą wydajność, ponieważ nie ma kosztów związanych z synchronizacją.
- HashTable jest wolniejsza z powodu synchronizacji.
-
Dziedziczenie:
-
HashMap jest częścią nowej Kolekcji Framework wprowadzonej w Javie 2 i dziedziczy po abstrakcyjnej klasie
AbstractMap
. -
HashTable jest starszą implementacją i dziedziczy bezpośrednio po klasie
Dictionary
.
-
HashMap jest częścią nowej Kolekcji Framework wprowadzonej w Javie 2 i dziedziczy po abstrakcyjnej klasie
-
Metody Legacy:
- HashMap nie zawiera żadnych metod legacy.
-
HashTable zawiera metody legacy, takie jak
elements()
icontains()
.
-
Kompatybilność z Kolekcjami:
- HashMap jest w pełni zgodna z nowym Java Collections Framework.
-
HashTable była implementowana przed wprowadzeniem Java Collections Framework, ale została później dostosowana do implementowania interfejsu
Map
.
Podsumowując, HashMap
jest zalecaną opcją w większości przypadków ze względu na większą wydajność i elastyczność. HashTable
jest używana rzadziej, głównie ze względów historycznych lub w specyficznych scenariuszach wielowątkowych, chociaż w takich przypadkach często lepszym wyborem jest ConcurrentHashMap
.
Podaj przykłady checked, unchecked exceptions oraz errors.
W Javie, wyjątki (exceptions
) i błędy (errors
) są dwoma głównymi kategoriami problemów, z którymi programiści mogą się spotkać. Oto przykłady każdego z nich:
Checked Exceptions
Checked exceptions to wyjątki, które muszą być albo obsłużone za pomocą bloku try-catch
, albo zadeklarowane w sygnaturze metody poprzez słowo kluczowe throws
. Są one sprawdzane w czasie kompilacji. Przykłady:
- IOException: Ten wyjątek jest wyrzucany, gdy występuje jakiś problem z operacjami wejścia/wyjścia, na przykład przy czytaniu plików.
- SQLException: Pojawia się podczas pracy z bazami danych, na przykład gdy zapytanie SQL jest błędne lub występują problemy z połączeniem.
- ClassNotFoundException: Wyrzucany, gdy próbuje się załadować klasę za pomocą jej nazwy, ale klasa nie jest znaleziona.
Unchecked Exceptions
Unchecked exceptions to wyjątki, które nie muszą być obsługiwane ani deklarowane w sygnaturze metody. Są one sprawdzane w czasie wykonania programu (runtime). Przykłady:
-
NullPointerException: Wyrzucany, gdy aplikacja próbuje użyć obiektu, który jest
null
. - ArrayIndexOutOfBoundsException: Pojawia się, gdy program próbuje uzyskać dostęp do indeksu tablicy poza jej zakresem.
- IllegalArgumentException: Wyrzucany, gdy metoda otrzymuje argument, który nie jest odpowiedni lub niewłaściwy.
Errors
Errors wskazują na poważne problemy, które zazwyczaj nie powinny być obsługiwane przez aplikację. Są to zazwyczaj problemy związane z środowiskiem wykonawczym Javy. Przykłady:
- OutOfMemoryError: Występuje, gdy JVM nie ma wystarczająco dużo pamięci do kontynuowania działania.
- StackOverflowError: Pojawia się, gdy stos wywołań metody jest zbyt głęboki, co zazwyczaj jest wynikiem rekurencji bez warunku kończącego.
- NoClassDefFoundError: Wyrzucany, gdy JVM nie może znaleźć klasy, którą wcześniej była w stanie znaleźć.
Te kategorie pomagają programistom w Javie zrozumieć, jak radzić sobie z różnymi typami wyjątków i błędów, zarówno podczas pisania kodu, jak i w trakcie jego wykonania.
Wyjaśnij pojęcie polimorfizmu w Javie.
Polimorfizm w Javie to koncepcja, która pozwala na wykonywanie jednej operacji na różne sposoby. W praktyce oznacza to, że można użyć jednego interfejsu do obsługi różnych typów danych. Istnieją dwa główne rodzaje polimorfizmu w Javie: statyczny (przeciążanie metod) i dynamiczny (nadpisywanie metod).
Dynamiczny Polimorfizm (Nadpisywanie Metod)
Dynamiczny polimorfizm, zwany również nadpisywaniem metod (method overriding
), występuje, gdy klasa dziedzicząca używa metody o tej samej nazwie, typie zwracanym i parametrach, co metoda w klasie bazowej.
Oto przykładowy kod demonstrujący polimorfizm w Javie poprzez nadpisywanie metod:
class Zwierze { public void wydajDzwiek() { System.out.println("Zwierzę wydaje dźwięk"); } } class Pies extends Zwierze { @Override public void wydajDzwiek() { System.out.println("Pies szczeka"); } } class Kot extends Zwierze { @Override public void wydajDzwiek() { System.out.println("Kot miauczy"); } } public class Main { public static void main(String[] args) { Zwierze mojeZwierze = new Zwierze(); Zwierze mojPies = new Pies(); Zwierze mojKot = new Kot(); mojeZwierze.wydajDzwiek(); // Wyświetla: Zwierzę wydaje dźwięk mojPies.wydajDzwiek(); // Wyświetla: Pies szczeka mojKot.wydajDzwiek(); // Wyświetla: Kot miauczy } }
W tym przykładzie, metoda wydajDzwiek()
jest nadpisana w klasach Pies
i Kot
. Dzięki polimorfizmowi, możemy używać obiektów Pies
i Kot
jako obiektów typu Zwierze
i wywoływać nadpisane metody.
Statyczny Polimorfizm (Przeciążanie Metod)
Statyczny polimorfizm, zwany również przeciążaniem metod (method overloading
), występuje, gdy w jednej klasie istnieje więcej niż jedna metoda o tej samej nazwie, ale z różnymi listami parametrów. Jest to sposób na stworzenie kilku metod o tej samej nazwie, które różnią się ilością lub typem parametrów.
Polimorfizm jest fundamentalnym aspektem programowania obiektowego w Javie, umożliwiającym tworzenie bardziej elastycznego i łatwego w utrzymaniu kodu.
Pytanie: Co to jest Lambda Expression w Javie?
Odpowiedź: Lambda Expression to krótka blok kodu, który umożliwia traktowanie funkcjonalności jako obiektu.
Napisz implementację wzorca Singleton w Javie.
Wzorzec Singleton w Javie to sposób projektowania klasy, który zapewnia, że tylko jedna instancja tej klasy może istnieć w całej aplikacji. Poniżej przedstawię przykładową implementację wzorca Singleton w Javie:
Implementacja Klasyczna
public class Singleton { // Prywatne statyczne pole przechowujące jedyną instancję klasy private static Singleton instance; // Prywatny konstruktor, aby uniemożliwić tworzenie obiektu z zewnątrz private Singleton() {} // Publiczna metoda statyczna dostarczająca instancję klasy public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } // Tutaj mogą być inne metody... }
Implementacja z Synchronizacją
W środowisku wielowątkowym, gdzie dostęp do klasy Singleton może odbywać się równocześnie z różnych wątków, przydatna jest synchronizacja:
public class Singleton { private static Singleton instance; private Singleton() {} public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } // Tutaj mogą być inne metody... }
Implementacja z Użyciem Wewnętrznej Klasy Statycznej (Lazy Loading)
Jest to bezpieczny sposób na utworzenie instancji klasy Singleton w środowisku wielowątkowym, który nie wymaga synchronizacji:
public class Singleton { private Singleton() {} private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); } public static Singleton getInstance() { return SingletonHolder.INSTANCE; } // Tutaj mogą być inne metody... }
Implementacja z Użyciem Enum (Najlepsza Praktyka)
public enum Singleton { INSTANCE; // Tutaj mogą być inne metody... }
W przypadku ostatniej metody, używamy typu enum
, który naturalnie zapewnia bezpieczeństwo wątkowe i gwarantuje, że instancja zostanie utworzona tylko raz. Jest to zalecana metoda implementacji Singleton w nowoczesnych aplikacjach Java.
Opisz zmiany wprowadzone w kolejnych wersjach Javy od wersji 8.
Java, będąca jednym z najpopularniejszych języków programowania, przeszła przez znaczące zmiany i udoskonalenia w kolejnych wersjach od Java 8. Poniżej przedstawiam kluczowe zmiany wprowadzone w kolejnych wydaniach Javy:
Java 8 (marzec 2014)
- Lambdy i Interfejsy Funkcyjne: Umożliwienie pisania bardziej zwięzłego i elastycznego kodu.
- Stream API: Wprowadzenie strumieni do przetwarzania danych w deklaratywnym stylu.
- Java Time API: Nowy API do obsługi daty i czasu.
- Default Methods w Interfejsach: Pozwala na dodawanie nowych metod do interfejsów bez naruszania istniejących implementacji.
- Nashorn JavaScript Engine: Nowa implementacja silnika JavaScript.
Java 9 (wrzesień 2017)
- Moduły (Project Jigsaw): Wprowadzenie systemu modułów do lepszego zarządzania zależnościami i strukturą aplikacji.
- JShell: Interaktywny REPL (Read-Eval-Print Loop) dla Javy.
- Ulepszenia Stream API: Nowe metody, takie jak takeWhile
, dropWhile
.
- Private Methods w Interfejsach: Możliwość definiowania metod prywatnych w interfejsach.
Java 10 (marzec 2018)
- Local-Variable Type Inference (var): Umożliwienie deklaracji zmiennych lokalnych z użyciem var
zamiast jawnej deklaracji typu.
- Time-Based Release Versioning: Wprowadzenie nowego modelu wersjonowania opartego na czasie.
Java 11 (wrzesień 2018)
- HTTP Client API: Standardowy klient HTTP obsługujący protokół HTTP/2.
- Usunięcie Java EE i CORBA Modułów: Moduły Java EE i CORBA zostały usunięte z JDK.
- String Methods: Nowe metody dla klas String
, takie jak isBlank
, lines
, strip
.
Java 12 (marzec 2019)
- Switch Expressions (Preview): Uproszczenie instrukcji switch
.
- JVM Constants API: Nowe API do modelowania stałych przekazywanych do i z JVM.
Java 13 (wrzesień 2019)
- Text Blocks (Preview): Wprowadzenie bloków tekstowych dla lepszego formatowania ciągów wieloliniowych.
- Reimplementacja Legacy Socket API: Nowa implementacja dla Socket API.
Java 14 (marzec 2020)
- Switch Expressions (Standard): Instrukcje switch
stają się oficjalną częścią języka.
- Records (Preview): Wprowadzenie rekordów, które są prostym sposobem na tworzenie klas danych.
- Pattern Matching dla instanceof (Preview): Uproszczenie użycia operatora instanceof
.
Java 15 (wrzesień 2020)
- Text Blocks (Standard): Bloki tekstowe stają się oficjalną częścią języka.
- Sealed Classes (Preview): Klasom zapieczętowanym można określić, które inne klasy mogą z nich dziedziczyć.
Java 16 (marzec 2021)
- Records (Standard): Rekordy stają się oficjalną częścią języka.
- Pattern Matching dla instanceof (Standard): Uproszczone instanceof
staje się standardem.
- JEP 338: Vector API (Incubator): Eksperymentalne API do wykonywania operacji wektorowych.
Java 17 (wrzesień 2021)
- Sealed Classes (Standard): Klasom zapieczętowanym stają się standardem.
- Pattern Matching dla switch (Preview): Rozszerzenie wzorców dopasowania dla instrukcji switch
.
Każda z tych wersji wnosiła istotne ulepszenia do języka i platformy Java, ułatwiając programowanie, poprawiając wydajność i wprowadzając nowe możliwości. Java kontynuuje ewolucję, dostosowując się do zmieniających się wymagań nowoczesnego programowania.
Pytanie: Jakie znasz sposoby zarządzania sesjami w aplikacjach webowych?
Odpowiedź: Zarządzanie sesjami w aplikacjach webowych można realizować za pomocą ciasteczek, URL rewriting, hidden form fields lub sesji HTTP.