Witam wszystkich! Dzisiaj kontynuuję przegląd pytań do wywiadu z programistą Java.
29. Czy w konstruktorze można zastosować funkcję return?
Tak, ale tylko bez wartości po prawej stronie słowa kluczowego return . Możesz użyć zwrotu; jako instrukcja pomocnicza w konstruktorze, aby pilnie zakończyć (przerwać) wykonywanie dalszego kodu i zakończyć inicjalizację obiektu. Załóżmy na przykład, że mamy klasę Kot i jeśli Kot jest bezdomny ( isHomeless = true , to chcemy zakończyć inicjalizację i nie wypełniać pozostałych pól (w końcu są nam nieznane, ponieważ kot jest bezdomny) :public Cat(int age, String name, boolean isHomeless) {
if (isHomeless){
this.isHomeless = isHomeless;
return;
}
this.isHomeless = isHomeless;
this.age = age;
this.name = name;
}
Ale jeśli mówimy o konkretnych wartościach, to słowo kluczowe return nie może zwrócić określonej wartości, ponieważ:
- kiedy zadeklarujesz konstruktora, nie będziesz mieć niczego podobnego do typu zwracanego;
- z reguły konstruktor jest wywoływany niejawnie podczas tworzenia instancji;
- konstruktor nie jest metodą: jest oddzielnym mechanizmem, którego jedynym celem jest inicjalizacja zmiennych instancji, tzn. używamy operatora new do utworzenia obiektu.
30. Czy konstruktor może zgłosić wyjątek?
Konstruktory działają z wyjątkami w taki sam sposób, jak metody. Metody pozwalają nam zgłaszać wyjątki poprzez zapisanie rzutów <ExceptionType> w nagłówku metody. Konstruktorzy pozwalają nam zrobić to samo. Kiedy dziedziczymy i definiujemy konstruktor klasy podrzędnej, możemy rozszerzyć typ wyjątku — na przykład IOException -> Wyjątek (ale nie odwrotnie). Użyjmy konstruktora klasy Cat jako przykładu konstruktora zgłaszającego wyjątek. Powiedzmy, że tworząc obiekt chcemy z konsoli wpisać imię i wiek:public Cat() throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
this.name = reader.readLine();
this.age = Integer.parseInt(reader.readLine());
}
Ponieważ funkcja reader.readLine() zgłasza wyjątek IOException, zapisujemy go w nagłówku jako możliwy zgłoszony wyjątek.
31. Jakie są elementy nagłówka klasy? Napisz przykład
Aby zilustrować elementy tworzące nagłówek klasy, spójrzmy na mały schemat:- elementy obowiązkowe znajdują się w nawiasach <>
- elementy opcjonalne znajdują się w {}
public final class Lion extends Cat implements WildAnimal
32. Jakie są elementy nagłówka metody? Napisz przykład
Rozważając elementy tworzące nagłówek metody, rozważmy ponownie mały schemat:- elementy obowiązkowe znajdują się w nawiasach <>
- elementy opcjonalne znajdują się w {}
public static void main(String[] args) throws IOException
33. Utwórz domyślny konstruktor w klasie potomnej, jeśli nie jest on jeszcze zdefiniowany w klasie bazowej (ale zdefiniowany jest inny konstruktor)
Nie jestem pewien, czy w pełni rozumiem pytanie, ale może to oznaczać, że w klasie nadrzędnej mamy takiego konstruktora:public Cat(int age, String name) {
this.age = age;
this.name = name;
}
W takim przypadku w klasie nadrzędnej zdecydowanie musimy zdefiniować konstruktor, który zainicjalizuje rodzica (tzn. wywoła konstruktor nadrzędny):
public class Lion extends Cat {
public Lion(int age, String name) {
super(age, name);
}
}
34. Kiedy używane jest słowo kluczowe this?
W Javie ma to dwa różne znaczenia. 1. Jest to odniesienie do aktualnego obiektu, np. this.age = 9 . Oznacza to, że odnosi się to do obiektu, w którym jest używane i do którego odnosi się kod z tym . Głównym celem jest poprawa czytelności kodu i uniknięcie niejednoznaczności. Na przykład, jeśli pole instancji i argument metody mają tę samą nazwę:public void setName(String name) {
this.name = name;
}
Oznacza to, że this.name jest polem obiektu, a name jest parametrem metody. Odniesienia this nie można używać w metodach statycznych. 2. W konstruktorze można to wywołać jak metodę, np. this(value) . W tym przypadku będzie to wywołanie innego konstruktora tej samej klasy. Zasadniczo podczas tworzenia obiektu możesz wywołać dwa konstruktory:
public Cat(int age, String name) {
this(name);
this.age = age;
}
public Cat(String name) {
this.name = name;
}
Podczas wywoływania pierwszego konstruktora w celu utworzenia obiektu Cat oba pola instancji zostaną pomyślnie zainicjowane. Jest tu kilka niuansów:
- this() działa tylko w konstruktorze.
- Odwołanie do innego konstruktora musi znajdować się w pierwszej linii bloku konstruktora (treści). Oznacza to, że konstruktor nie może wywołać więcej niż jednego (innego) konstruktora swojej klasy.
35. Co to jest inicjator?
O ile rozumiem, to pytanie dotyczy zwykłych i statycznych bloków inicjujących. Najpierw przypomnijmy sobie, czym jest inicjalizacja. Inicjalizacja to tworzenie, aktywacja, przygotowanie i definicja pól. Przygotowanie programu lub komponentu do użycia. Jak pamiętasz, kiedy tworzysz obiekt, zmienna klasy może zostać zainicjowana natychmiast po jej zadeklarowaniu:class Cat {
private int age = 9;
private String name = "Tom";
Lub ustaw po fakcie za pomocą konstruktora:
class Cat {
private int age;
private String name;
public Cat(int age, String name) {
this.age = age;
this.name = name;
}
Ale jest inny sposób: możesz ustawić zmienną instancji za pomocą bloku inicjującego, który ma postać nawiasów klamrowych {} wewnątrz klasy, bez nazwy (jak bezimienna metoda lub konstruktor):
class Cat {
private int age;
private String name;
{
age = 10;
name = "Tom";
}
Blok inicjujący to fragment kodu ładowany podczas tworzenia obiektu. Takie bloki są zwykle używane do wykonywania pewnych złożonych obliczeń, które są wymagane podczas ładowania klasy. Wyniki tych obliczeń można ustawić jako wartości zmiennych. Oprócz zwykłych bloków inicjujących istnieją bloki statyczne. Wyglądają tak samo, ale mają słowo kluczowe static przed otwierającym nawiasem klamrowym:
class Cat {
private static int age;
private static String name;
static{
age = 10;
name = "Tom";
}
Ten blok jest taki sam jak poprzedni. Ale jeśli zwykły jest wykonywany podczas inicjowania każdego obiektu, to statyczny jest wykonywany tylko raz, kiedy klasa jest ładowana. Z reguły pewne złożone obliczenia wykonywane są w bloku statycznym, służącym do inicjalizacji zmiennych klasy statycznej. Te same ograniczenia dotyczą bloku statycznego, co metody statyczne: nie można używać danych niestatycznych, takich jak odwołanie do bieżącego obiektu ( this ) w bloku statycznym. Teraz możemy przyjrzeć się kolejności inicjalizacji klasy (wraz z jej klasą nadrzędną), aby lepiej zrozumieć, kiedy dokładnie wywoływane są bloki inicjujące.
36. Mając publiczną klasę Child, która rozszerza Parent, zapisz kolejność inicjalizacji obiektu
Podczas ładowania klasy Child kolejność inicjalizacji będzie następująca:- Pola klasy statycznej klasy Parent .
- Statyczny blok inicjujący klasy Parent .
- Pola statyczne klasy Сhild .
- Statyczny blok inicjujący klasy Child .
- Pola niestatyczne klasy Parent .
- Niestatyczny blok inicjujący klasy Parent .
- Konstruktor klasy nadrzędnej .
- Pola niestatyczne klasy Сhild .
- Niestatyczny blok inicjujący klasy Сhild .
- Konstruktor klasy Сhild .
37. Jakie znasz relacje pomiędzy klasami (obiektami)?
W Javie istnieją dwa rodzaje zmiennych: typy pierwotne i odniesienia do pełnoprawnych obiektów.- Relacje IS-A
Lion IS-A Cat
(ale nie każdy kot jest lwem ) Ta sama sytuacja ma miejsce w przypadku interfejsów. Jeśli klasa Lion implementuje interfejs WildAnimal , to one również istnieją w relacji:
Lion IS-A WildAnimal
- Związek MA-A
Car HAS-A Passenger
I odwrotnie: jeśli Pasażer ma odniesienie do Car , to będzie to relacja:
Passenger HAS-A Car
38. Jakie znasz relacje z obiektami skojarzeniowymi?
Agregacja i kompozycja to nic innego jak szczególne przypadki asocjacji. Agregacja to relacja, w której jeden obiekt jest częścią drugiego. Na przykład pasażer może znajdować się w samochodzie. Co więcej, pasażerów może być wielu lub wcale (a jeśli mówimy o Tesli, może nie być kierowcy). Na przykład:public class Car {
private List passengers = new ArrayList<>();
void setPassenger(Passenger passenger) {
passengers.add(passenger);
}
void move() {
for (Passenger passenger : passengers) {
System.out.println("Transporting passenger - " + passenger.toString());
}
passengers.clear();
}
}
Innymi słowy, liczba pasażerów (w ogóle) nie jest dla nas istotna: funkcjonalność klasy Car nie jest od tego zależna. Agregacja oznacza również, że gdy inny obiekt korzysta z jednego obiektu, pierwszy obiekt może być używany przez inne obiekty. Na przykład ten sam uczeń może należeć zarówno do klubu dziewiarskiego, jak i do zespołu rockowego i jednocześnie uczęszczać na zajęcia z hiszpańskiego. Jak możesz sobie wyobrazić, agregacja to luźniejsza relacja asocjacyjna między klasami. Kompozycja to jeszcze ściślejszy związek, w którym obiekt nie jest tylko częścią innego obiektu, ale działanie jednego obiektu jest w dużym stopniu zależne od drugiego. Na przykład samochód ma silnik. Silnik może istnieć bez samochodu, ale poza samochodem jest bezużyteczny. A samochód nie może działać bez silnika:
public class Car {
private Engine engine;
public Car(Engine engine) {
this.engine = engine;
}
void startMoving() {
engine.start();
...
}
Kompozycja oznacza również, że gdy inny przedmiot korzysta z obiektu, pierwszy obiekt nie może należeć do żadnego innego obiektu. Wracając do naszego przykładu, silnik może należeć tylko do jednego samochodu, a nie do dwóch lub więcej jednocześnie. Myślę, że na dzisiaj wystarczy, więc na tym poprzestaniemy.
GO TO FULL VERSION