JavaRush /Blog Java /Random-PL /Analiza pytań i odpowiedzi z rozmów kwalifikacyjnych dla ...

Analiza pytań i odpowiedzi z rozmów kwalifikacyjnych dla programisty Java. Część 11

Opublikowano w grupie Random-PL
Cześć! Nawet najszybszy statek bez kursu będzie po prostu dryfował po falach. Jeśli czytasz teraz mój artykuł, na pewno masz cel. Najważniejsze, aby nie zejść na manowce, ale podążać swoją drogą do końca - zostać programistą Java. Dzisiaj chcę kontynuować moją analizę ponad 250 pytań do programistów Java, która pomoże Ci uzupełnić niektóre luki w teorii. Analiza pytań i odpowiedzi z rozmów kwalifikacyjnych dla programisty Java.  Część 11 - 1

97. Czy w przypadku redefinicji Równych narzucane są warunki redefinicji umowy?

Nadpisana metoda równości() musi spełniać następujące warunki (reguły):
  • zwrotność - dla dowolnej wartości x wyrażenie takie jak x.equals(x) powinno zawsze zwracać wartość true (gdy x != null ).

  • symetria - dla dowolnych wartości x i y wyrażenie w postaci x.equals(y) musi zwracać true tylko wtedy, gdy y.equals(x) zwraca true .

  • przechodniość - dla dowolnych wartości x , y i z , jeśli x.equals(y) zwraca true i y.equals(z) również zwraca true , to x.equals(z) musi zwracać true .

  • spójność - dla dowolnych wartości x i y powtórne wywołanie x.equals(y) zawsze zwróci wartość poprzedniego wywołania tej metody pod warunkiem, że pola użyte do porównania obu obiektów nie uległy zmianie pomiędzy wywołaniami .

  • porównanie null - dla dowolnej wartości x wywołanie x.equals(null) zwróci false .

98. Co się stanie, jeśli nie zastąpisz wartości Equal i HashCode?

W tym przypadku hashCode() zwróci liczbę wygenerowaną na podstawie lokalizacji pamięci, w której przechowywany jest dany obiekt. Oznacza to, że dwa obiekty o dokładnie tych samych polach otrzymają różne wartości podczas wywoływania niezastąpionej funkcji hashCode() (w końcu są przechowywane w różnych lokalizacjach pamięci). Niezastąpiona metoda równa się() porównuje odniesienia, aby sprawdzić, czy wskazują one na ten sam obiekt, czy nie. Oznacza to, że porównanie odbywa się poprzez == i w przypadku obiektów o tych samych polach zawsze zwróci false . Prawdziwe będzie tylko przy porównywaniu odniesień do tego samego obiektu. Czasami logicznym jest niezastąpienie tych metod. Na przykład chcesz, aby wszystkie obiekty określonej klasy były unikalne, a zastąpienie tych metod tylko zepsuje logikę wyjątkowości. Najważniejsze jest zrozumienie niuansów metod przesłoniętych i niezastąpionych i zastosowanie obu podejść w zależności od sytuacji.

99. Dlaczego symetria jest prawdziwa tylko wtedy, gdy x.equals(y) zwraca prawdę?

Trochę dziwne pytanie. Jeśli obiekt A jest równy obiektowi B, to obiekt B jest równy obiektowi A. Jeśli B nie jest równy obiektowi A, to jak możliwe jest coś odwrotnego? To jest prosta logika. Analiza pytań i odpowiedzi z rozmów kwalifikacyjnych dla programisty Java.  Część 11 - 2

100. Czym jest kolizja w HashCode? Jak sobie z tym poradzić?

Kolizja hashCode to sytuacja, w której dwa różne obiekty mają tę samą wartość hashCode . Jak to jest możliwe? Faktem jest, że hashcode jest mapowany na typ Integer , który z kolei ma zakres od -2147483648 do 2147483647, czyli około 4 miliardów różnych liczb całkowitych. Zakres ten jest ogromny, jednak nie jest nieskończony. Dlatego możliwe są sytuacje, gdy dwa zupełnie różne obiekty mają ten sam kod skrótu. Jest to bardzo mało prawdopodobne, ale możliwe. Źle zaimplementowana funkcja skrótu może również zwiększyć częstotliwość występowania identycznych kodów skrótu, które zwrócą np. liczby z małego zakresu, co zwiększy ryzyko kolizji. Aby walczyć z kolizją, trzeba mieć dobrą implementację metody hashCode , aby rozrzut wartości był maksymalny, a szansa na powtórzenie wartości minimalna.

101. Co się stanie jeśli element uczestniczący w kontrakcie HashCode zmieni swoją wartość?

Jeśli element biorący udział w obliczaniu kodu skrótu został zmieniony, wówczas zmieniony zostanie kod skrótu samego obiektu (jeśli funkcja mieszająca jest dobra). Dlatego w HashMap zaleca się stosowanie jako klucza obiektów niezmiennych (niezmiennych), ponieważ ich stanu wewnętrznego (pól) nie można zmienić po utworzeniu. W związku z tym ich kod skrótu również nie jest konwertowany po utworzeniu. Jeśli użyjesz obiektu zmiennego jako klucza, to gdy zmienisz pola tego obiektu, jego kod skrótu ulegnie zmianie, w wyniku czego możesz stracić tę parę w HashMap . Przecież będzie on przechowywany w zasobniku na oryginalny kod skrótu, a po jego zmianie będzie przeszukiwany w innym zasobniku. Analiza pytań i odpowiedzi z rozmów kwalifikacyjnych dla programisty Java.  Część 11 - 3

102. Napisz metody Equals i HashCode dla klasy Student, która składa się z pól String name i int age

public class Student {
int age;
String name;

 @Override
 public boolean equals(final Object o) {
   if (this == o) {
     return true;
   }
   if (o == null || this.getClass() != o.getClass()) {
     return false;
   }

   final Student student = (Student) o;

   if (this.age != student.age) {
     return false;
   }
   return this.name != null ? this.name.equals(student.name) : student.name == null;
 }

 @Override
 public int hashCode() {
   int result = this.age;
   result = 31 * result + (this.name != null ? this.name.hashCode() : 0);
   return result;
 }
}
Równa się:
  • Najpierw porównujemy linki bezpośrednio, bo jeśli linki prowadzą do tego samego obiektu, to jaki jest sens kontynuowania sprawdzania? Wszystko i tak będzie prawdą .

  • Sprawdzanie wartości null i pasujących typów klas, ponieważ jeśli obiekt jest argumentem null lub innego typu, oznacza to, że obiekty nie są równe - false .

  • Rzutowanie obiektu argumentu na jeden typ (w przypadku, gdy był to obiekt typu nadrzędnego).

  • Porównanie prymitywnego pola klasy (w końcu wystarczy porównanie przez =! ), jeśli pole nie jest równe - false .

  • Sprawdzanie nieprymitywnego pola pod kątem wartości null i równości (w String metoda jest nadpisywana i będzie porównywana poprawnie), jeśli oba pola mają wartość null lub są równe , sprawdzanie kończy się i metoda zwraca wartość true .

Kod skrótu:
  • Ustawienie początkowej wartości kodu skrótu na prymityw wieku obiektu .

  • Mnożenie bieżącego kodu skrótu przez 31 (dla większego rozrzutu) i dodanie do niego kodu skrótu nieprymitywnego pola tekstowego (jeśli nie ma wartości null).

  • Zwracanie wyniku.

  • W wyniku tego zastąpienia kodu skrótu obiekty o tej samej nazwie i wartościach int zawsze będą zwracać tę samą wartość.

103. Jaka jest różnica pomiędzy użyciem if (obj instancja Studenta) i if (getClass() == obj.getClass())?

Przyjrzyjmy się, co robi każde podejście:
  • instancja sprawdza, czy odwołanie do obiektu po lewej stronie jest instancją typu po prawej stronie, czy jakimś jego podtypem.

  • getClass() == ... sprawdza tożsamość typu.

Oznacza to, że jeśli funkcja getClass() sprawdza pełną tożsamość klasy, instancja zwróci wartość true, nawet jeśli obiekt jest tylko podtypem, co może zapewnić nam większą elastyczność podczas aktywnego korzystania z polimorfizmu. Właściwie oba podejścia są dobre, jeśli zrozumiesz cechy ich pracy i zastosujesz je we właściwych miejscach.

104. Podaj krótki opis metody clone().

Clone() to metoda klasy Object , której celem jest utworzenie i zwrócenie klona bieżącego obiektu (kopii bieżącego obiektu). Analiza pytań i odpowiedzi z rozmów kwalifikacyjnych dla programisty Java.  Część 11 - 4Aby z niego skorzystać, musisz zaimplementować interfejs znacznika Cloneable :
Student implements Cloneable
I zastąp samą metodę clone() :
@Override
protected Object clone() throws CloneNotSupportedException {
 return super.clone();
}
Przecież w klasie Object jest on chroniony, czyli będzie widoczny tylko w samej klasie Student , ale nie będzie widoczny dla klas z zewnątrz.

105. Jaka jest specyfika metody clone() działającej z polami obiektu typu referencyjnego?

Podczas klonowania obiektów kopiowane są tylko wartości pierwotne i wartości odniesień do obiektów. Oznacza to, że jeśli obiekt ma w swoim polu wewnętrznym link do innego obiektu, to sklonowane zostanie tylko to łącze, ale sam ten inny obiekt nie zostanie sklonowany. W rzeczywistości nazywa się to klonowaniem powierzchniowym. A co, jeśli potrzebujesz pełnoprawnego klonowania z klonowaniem wszystkich zagnieżdżonych obiektów? Jak zadbać o to, aby nie były to kopie linków, a pełnoprawne klony obiektów z innymi zajętymi komórkami pamięci na stercie? Tak naprawdę wszystko jest dość proste - w tym celu trzeba także nadpisać metodę clone() w każdej klasie tych wewnętrznych obiektów i dodać interfejs znacznika - Cloneable . Wtedy kopiowane nie będą odniesienia do obiektów, ale same obiekty, bo teraz one także mają możliwość kopiowania siebie.

Wyjątki

106. Jaka jest różnica między błędem a wyjątkiem?

Zarówno wyjątki, jak i błędy są podklasami klasy Throwable . Mają jednak swoje różnice. Błąd wskazuje na problem, który występuje głównie z powodu niewystarczających zasobów systemowych. A nasza aplikacja nie powinna wykrywać tego typu problemów. Przykładami błędów są awaria systemu i błąd braku pamięci. Błędy występują najczęściej w czasie wykonywania, ponieważ są typu niesprawdzonego. Analiza pytań i odpowiedzi z rozmów kwalifikacyjnych dla programisty Java.  Część 11 - 5Wyjątki to problemy, które mogą wystąpić w czasie wykonywania i kompilacji. Zwykle dzieje się tak w kodzie napisanym przez programistów. Oznacza to, że wyjątki są bardziej przewidywalne i bardziej zależne od nas jako programistów. Jednocześnie błędy są bardziej losowe i bardziej niezależne od nas, a raczej zależą od problemów z samym systemem, w którym działa nasza aplikacja.

107. Jaka jest różnica między zaznaczonym a niesprawdzonym, wyjątkiem, rzutem, rzutem.

Jak powiedziałem wcześniej, wyjątkiem jest błąd podczas wykonywania programu i podczas kompilacji, który wystąpił w kodzie napisanym przez programistę (spowodowany jakąś nienormalną sytuacją). Zaznaczony jest typ wyjątku, który należy zawsze obsłużyć za pomocą mechanizmu try-catch lub zgłosić do powyższych metod. Zgłoszenia są używane w nagłówku metody w celu wskazania możliwych wyjątków zgłoszonych przez metodę. Oznacza to, że jest to mechanizm „wrzucania” wyjątków do powyższych metod. Niezaznaczony to typ wyjątku, który nie wymaga obsługi i jest zazwyczaj mniej przewidywalny i mniej prawdopodobny. W razie potrzeby można je jednak również poddać obróbce. Throw jest używany podczas ręcznego zgłaszania wyjątku, na przykład:
throw new Exception();

108. Jaka jest hierarchia wyjątków?

Hierarchia wyjątków jest bardzo duża i rozbudowana, wręcz zbyt obszerna, aby wszystko o niej tutaj opowiedzieć. Dlatego rozważymy tylko jej kluczowe ogniwa: Analiza pytań i odpowiedzi z rozmów kwalifikacyjnych dla programisty Java.  Część 11 - 6Tutaj na samym szczycie hierarchii widzimy klasę - Throwable - klasę ogólną, przodka hierarchii wyjątków, która z kolei dzieli się na:
  • Błąd - błędy krytyczne, których nie da się sprawdzić.
  • Wyjątek - sprawdzone wyjątki.
Wyjątek jest podzielony na różne niesprawdzone wyjątki środowiska wykonawczego i różne sprawdzone wyjątki.

109. Co to jest wyjątek sprawdzony i niesprawdzony?

Jak już mówiłem:
  • Zaznaczone - wyjątki, które musisz jakoś obsłużyć, czyli albo przetworzyć je w bloku try-catch , albo „przekazać” do powyższej metody. Aby to zrobić, w sygnaturze metody, po wyszczególnieniu argumentów metody, należy użyć słowa kluczowego trows <exception type> , które informuje użytkowników metody, że metoda może zgłosić ten wyjątek (coś w rodzaju ostrzeżenia) i przekazuje odpowiedzialność za obsługę wyjątku dla użytkowników tej metody.

  • Niezaznaczone - wyjątki, których nie trzeba obsługiwać, ponieważ nie są sprawdzane w czasie kompilacji i z reguły są bardziej nieprzewidywalne. Oznacza to, że główna różnica w przypadku sprawdzania polega na tym, że dla nich te mechanizmy łapania lub rzucania działają tak samo, ale nie są obowiązkowe.

101. Napisz przykład przechwytywania i obsługi wyjątku w bloku try-catch metody

try{                                                 // начало блока перехвата
 throw new Exception();                             // ручной бросок исключения
} catch (Exception e) {                              // данное исключение и его потомки будут перехватываться
 System.out.println("Упс, что-то пошло не так =("); // вывод некоторого исключения в консоль
}

102. Napisz przykład przechwytywania i obsługi wyjątku przy użyciu własnych wyjątków

Najpierw napiszmy własną klasę wyjątków, która dziedziczy po Wyjątku i zastępuje jej konstruktor komunikatem o błędzie:
public class CustomException extends Exception {

 public CustomException(final String message) {
   super(message);
 }
}
Cóż, wtedy rzucimy go ręcznie i przechwycimy, jak w poprzednim pytaniu:
try{
 throw new CustomException("Упс, что-то пошло не так =(");
} catch (CustomException e) {
 System.out.println(e.getMessage());
}
I znowu, kiedy go uruchomisz, otrzymasz na konsolę następujące dane wyjściowe:
Ups, coś poszło nie tak =(
Analiza pytań i odpowiedzi z rozmów kwalifikacyjnych dla programisty Java.  Część 11 - 7Więcej informacji na temat wyjątków można znaleźć tutaj . Cóż, to wszystko na dzisiaj! Do zobaczenia w kolejnej części!
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION