CodeGym /Blog Java /Random-PL /Przeglądanie pytań i odpowiedzi z rozmowy kwalifikacyjnej...
John Squirrels
Poziom 41
San Francisco

Przeglądanie pytań i odpowiedzi z rozmowy kwalifikacyjnej na stanowisko programisty Java. Część 5

Opublikowano w grupie Random-PL
Cześć cześć! Programiści Java są dziś bardzo poszukiwani. Oczywiście nie mogę zapewnić Ci oferty pracy, ale postaram się pomóc Ci zdobyć nową wiedzę i uzupełnić braki. Kontynuujmy zatem przegląd pytań do wywiadu z programistą Java. Linki do poprzednich części recenzji znajdziesz na końcu artykułu. Przeglądanie pytań i odpowiedzi z rozmowy kwalifikacyjnej na stanowisko programisty Java.  Część 5 - 1

39. Jakie są modyfikatory dostępu w Javie? Nazwij je. Do czego są używane?

Wcześniej omawiałem modyfikatory dostępu w pytaniu dotyczącym elementów Java używanych do osiągnięcia enkapsulacji. Ale mimo to przypomnę. Modyfikatory dostępu w Javie to słowa kluczowe opisujące poziom dostępu przyznanego konkretnemu komponentowi Java. Istnieją następujące modyfikatory dostępu:
  • public — element oznaczony tym modyfikatorem jest publiczny. Innymi słowy, pola i metody oraz klasy zadeklarowane za pomocą modyfikatora public są widoczne dla innych klas zarówno w ich własnym pakiecie, jak iw pakietach zewnętrznych;
  • chroniony — element oznaczony tym modyfikatorem jest dostępny z dowolnego miejsca w swojej klasie w bieżącym pakiecie lub klasach pochodnych, nawet jeśli znajdują się one w innych pakietach;
  • wartość domyślna (lub brak modyfikatora) ma zastosowanie pośrednie, gdy nie wskazano żadnego modyfikatora dostępu. Jest podobny do poprzedniego, z tą różnicą, że jest widoczny w klasach pochodnych znajdujących się w innych pakietach;
  • private — jest to najbardziej prywatny ze wszystkich modyfikatorów. Umożliwia dostęp do elementu tylko w obrębie bieżącej klasy.

40. Wymień główne cechy metod statycznych i niestatycznych

Główna różnica polega na tym, że metody statyczne należą do klasy. Tak naprawdę nie ma potrzeby tworzenia instancji tej klasy — metody statyczne można wywoływać po prostu z poziomu klasy. Załóżmy na przykład, że mamy statyczną metodę głaskania kota:
public class CatService {
   public static void petTheCat(Cat cat) {
       System.out.println("Pet the cat: " + cat.getName());
   }
Nie potrzebujemy instancji klasy CatService , aby ją wywołać:
Cat cat = new Cat(7, "Bobby");
CatService.petTheCat(cat);
Natomiast zwykłe metody są powiązane (należą) do obiektu. Aby je wywołać należy posiadać instancję (obiekt), na której zostanie wywołana metoda. Załóżmy na przykład, że nasz kot ma niestatyczną metodę meow() :
class Cat {
   public void meow() {
       System.out.println("Meow! Meow! Meow!");
   }
Aby wywołać tę metodę, potrzebujemy konkretnej instancji kota:
Cat cat = new Cat(7, "Bobby");
cat.meow();

41. Jakie są główne ograniczenia dotyczące metod statycznych i niestatycznych?

Jak powiedziałem wcześniej, głównym ograniczeniem zwykłej (niestatycznej) metody jest to, że zawsze musi istnieć jakaś instancja, w której metoda jest wywoływana. Ale metoda statyczna tego nie wymaga. Ponadto metoda statyczna nie może używać odniesienia this do elementów obiektu, ponieważ dla tej metody istnieje już bieżący obiekt.

42. Co oznacza słowo kluczowe static? Czy metodę statyczną można zastąpić lub przeciążyć?

Element oznaczony słowem kluczowym static nie należy do instancji klasy, lecz do samej klasy. Jest ładowany, gdy ładowana jest sama klasa. Elementy statyczne są takie same dla całego programu, natomiast elementy niestatyczne są takie same tylko dla konkretnego obiektu. Następujące elementy mogą być statyczne:
  • pola klasy;
  • blok inicjalizacyjny klasy;
  • metoda klasy;
  • zagnieżdżone klasy danej klasy (oczywiście jest to również tautologia).
Metody statycznej nie można przesłonić: należy ona do klasy i nie jest dziedziczona, ale jednocześnie może zostać przeciążona.

43. Czy metoda może być jednocześnie statyczna i abstrakcyjna?

Odpowiedziałem już na to w poprzednim artykule: metoda nie może być jednocześnie abstrakcyjna i statyczna. Jeśli metoda jest abstrakcyjna, oznacza to, że należy ją zastąpić w klasie potomnej. Jednak metoda statyczna należy do klasy i nie można jej zastąpić. Tworzy to sprzeczność, którą kompilator zauważy i zmartwi się. Jeśli znajdziesz się w takiej sytuacji, powinieneś poważnie zastanowić się nad poprawnością architektury swojej aplikacji (podpowiedź: coś jest z nią wyraźnie nie tak). Przeglądanie pytań i odpowiedzi z rozmowy kwalifikacyjnej na stanowisko programisty Java.  Część 5 - 2

44. Czy metody statyczne można stosować pośród metod niestatycznych? I wzajemnie? Dlaczego?

Metody statyczne możemy stosować w metodach niestatycznych. Nic temu nie stoi na przeszkodzie. To powiedziawszy, sytuacja odwrotna nie jest możliwa: metoda statyczna nie może używać metody niestatycznej bez odniesienia do konkretnej instancji klasy. Pamiętaj, że statyczni członkowie klasy nie mają dostępu do tej referencji: możesz mieć tyle konkretnych obiektów klasy, ile chcesz, a każdy z nich będzie zawierał this referencję , która jest samoodniesieniem. Jak więc ustalić, którego odniesienia użyć? Nie. Dlatego elementy statyczne nie mogą odnosić się do niestatycznych bez odniesienia do konkretnego obiektu. Zasadniczo metoda statyczna może używać metody niestatycznej tylko wtedy, gdy ma odwołanie do określonego obiektu. Na przykład taki, który pojawił się jako argument metody:
public static void petTheCat(Cat cat) {
   System.out.println("Pet the cat: " + cat.getName());
}
Widzimy tutaj, że statyczna metoda petTheCat() wywołuje getName , zwykłą niestatyczną metodę obiektu Cat .

45. Co to jest interfejs? Czy może istnieć ostateczny interfejs?

Przypomnijmy, że Java nie ma wielokrotnego dziedziczenia. Interfejsy są dla niego czymś w rodzaju alternatywy. Interfejs jest jak bardzo uproszczona klasa. Definiują funkcjonalność, ale nie konkretną implementację. Zadanie to pozostawiono klasom implementującym te interfejsy. Przykład interfejsu:
public interface Animal {
    void speak();
}
Przykład implementacji interfejsu przez klasę
class Cat implements Animal {

   @Override
   public void speak() {
       System.out.println("Meow! Meow! Meow!");
   }
}
Oto najważniejsza rzecz, którą należy wiedzieć na temat korzystania z interfejsów:
  1. Metody interfejsu mogą zawierać tylko nagłówek. Nie mogą mieć określonej treści metody, tj. muszą być abstrakcyjne (chociaż nie używają słowa kluczowego streszczenie). Istnieją wyjątki: metody statyczne i metody domyślne, które wymagają treści metody.

  2. Klasa może implementować wiele interfejsów (jak powiedziałem, interfejsy są alternatywą dla wielokrotnego dziedziczenia). Nazwy interfejsów oddzielane są przecinkami w nagłówku metody: klasa Lion implementuje Animal, Wild .

  3. Interfejsy są tworzone przy użyciu słowa kluczowego interfejs .

  4. Kiedy klasa implementuje interfejs, używamy słowa kluczowego implements .

  5. Klasa implementująca określony interfejs musi implementować wszystkie swoje metody abstrakcyjne lub musi zadeklarować się jako abstrakcyjna.

  6. Głównym celem stosowania interfejsów jest implementacja polimorfizmu (nadanie obiektowi możliwości przyjmowania wielu form).

  7. Z reguły modyfikatory dostępu dla metod nie są wskazywane w interfejsach: domyślnie są one publiczne i nie można określić innych modyfikatorów niż public . Począwszy od wersji Java 9, w metodach można używać prywatnych modyfikatorów.

  8. Domyślnie zmienne interfejsu są statyczne i finalne . Innymi słowy, są to stałe — zawsze muszą być inicjowane bezpośrednio w interfejsie.

  9. Nie można utworzyć instancji interfejsu.

Odpowiedź na pytanie, czy interfejsy mogą być ostateczne, brzmi oczywiście: nie. Rzeczywiście, cały sens posiadania interfejsów polega na tym, aby je zaimplementować. A jak wszyscy dobrze pamiętamy, końcowy modyfikator na poziomie klasy powoduje, że klasa nie jest dziedziczona, a w przypadku interfejsu – niemożliwa do zaimplementowania. Po co nam interfejs, którego nie możemy wdrożyć i używać? Masz rację – nie zrobilibyśmy tego! I kompilator się zgadza. :) Przeglądanie pytań i odpowiedzi z rozmowy kwalifikacyjnej na stanowisko programisty Java.  Część 5 - 3Właściwie wraz z wprowadzeniem statycznych metod interfejsu od Java 8 może to mieć sens, ale nie zmienia to faktu, że interfejs nie może być ostateczny. O interfejsach mówiłem bardzo powierzchownie, ponieważ jest to szeroki temat. Więcej na ten temat znajdziesz w artykułach na temat interfejsów w Javie i różnicy pomiędzy klasami abstrakcyjnymi a interfejsami .

46. ​​Gdzie można zainicjować pola statyczne?

Pola statyczne można inicjować:
  • natychmiast po deklaracji, używając znaku równości ( = );
  • w statycznym bloku inicjującym;
  • w niestatycznym bloku inicjującym (ale musisz zrozumieć, że za każdym razem, gdy tworzony jest obiekt, pole statyczne zostanie nadpisane, gdy ten blok inicjujący zostanie wykonany;
  • w konstruktorze klas. Za każdym razem, gdy wywoływany jest konstruktor (tzn. za każdym razem, gdy przy użyciu tego konstruktora tworzony jest obiekt), pole zostanie nadpisane;
  • w metodach statycznych;
  • w metodach niestatycznych;
  • w zagnieżdżonych klasach statycznych i niestatycznych, lokalnych i anonimowych.

47. Czym są zajęcia anonimowe?

Klasy anonimowe to klasy, które nie mają własnego typu. O czym ja mówię? Kiedy rozmawialiśmy o interfejsach, wspomniałem, że nie można utworzyć instancji obiektu: można utworzyć jedynie instancję klasy, która implementuje interfejs. Co się stanie, jeśli nie chcesz, aby jakaś klasa implementowała interfejs, ale potrzebujesz obiektu, który implementuje interfejs? I prawdopodobnie będzie to jedyne zastosowanie obiektu. I nie ma potrzeby tworzenia pełnoprawnej klasy implementacyjnej. Jak byś to zrobił? Zgadza się! Korzystając z anonimowej klasy! Przeglądanie pytań i odpowiedzi z rozmowy kwalifikacyjnej na stanowisko programisty Java.  Część 5 - 4Załóżmy, że mamy interfejs Animal :
public final interface Animal {
   public void speak();
}
Jeśli chcemy użyć anonimowej klasy do utworzenia instancji danego interfejsu:
Animal cat = new Animal() {
   @Override
   public void speak() {
       System.out.println("Meow! Meow! Meow!");
   }
};
Następnie możesz bezpiecznie używać tego obiektu i zaimplementowanej w nim metody mówienia() . Innymi słowy, anonimowa klasa implementuje interfejs i wszystkie jego abstrakcyjne metody tu i teraz. W przeciwnym razie nie bylibyśmy w stanie utworzyć obiektu interfejsu/klasy abstrakcyjnej, ponieważ istniałyby niezaimplementowane/abstrakcyjne metody. Jak wspomniałem, klasy anonimowe służą nie tylko do implementowania abstrakcyjnych metod interfejsu, ale także do implementowania abstrakcyjnych metod klasy abstrakcyjnej. Takie podejście sprawdza się w sytuacjach, gdy obiekt jest używany jednorazowo lub gdy dana implementacja metody jest potrzebna tylko raz. Nie ma potrzeby tworzenia osobnej klasy, która będzie implementować wymaganą klasę/interfejs abstrakcyjny. Ale zauważam też, że zajęcia anonimowe są rzadko wykorzystywane w pracy. Z reguły zwykłe zajęcia są nadal preferowane. Więcej o zajęciach anonimowych możesz przeczytać w tym artykule .

48. Czym są klasy prymitywne?

Myślę, że jest to pytanie wprowadzające w błąd, być może podchwytliwe, ponieważ w Javie nie ma czegoś takiego jak klasy prymitywne. Istnieje tylko koncepcja typów pierwotnych, którą rozważaliśmy wcześniej. Przypominamy, że Java ma 8 typów pierwotnych: byte , short , int , long , float , double , char , boolean .

49. Co to jest klasa opakowująca?

Głównym problemem związanym z używaniem typów pierwotnych w Javie jest to, że nie są one klasami, a Java jest językiem OOP. Oznacza to, że programy napisane w tym języku sprowadzają się do interakcji pomiędzy obiektami. Ale prymitywy nie są przedmiotami. Nie posiadają metod, nawet standardowych metod klasy Object . Ale co, jeśli będziemy musieli użyć prymitywu jako klucza na mapie ? Następnie musimy wywołać jego metodę hashCode() . Możesz tam także wywołać metodę równości() . Co wtedy? Jest mnóstwo momentów, w których potrzebujesz zajęć, a nie prymitywów. To sprawia, że ​​prymitywy są bezużytecznymi i niepożądanymi elementami programu, ponieważ naruszają samą ideę OOP. Ale sytuacja nie jest tak zła, jak się wydaje. W końcu Java ma koncepcję prymitywnych opakowań. W Javie każdy typ pierwotny ma bliźniaka — klasę opakowującą.
  • bajt -> Bajt.klasa
  • krótki -> Krótki.klasa
  • int -> Liczba całkowita.klasa
  • długi -> Długi.klasa
  • float -> Float.class
  • double -> Double.class
  • char -> Klasa.postaci
  • wartość logiczna -> Wartość logiczna.klasa
Typy te reprezentują typy proste, ale w pełnoprawnych klasach z wieloma zróżnicowanymi i pomocnymi metodami. Aby umożliwić wygodne korzystanie z tych klas, wprowadzono koncepcje autoboxingu i unboxingu. Autoboxing to automatyczna konwersja typu pierwotnego na jego analogiczną klasę, jeśli jest to konieczne (na przykład konwersja int na Integer ). Rozpakowywanie to proces odwrotny: automatyczna konwersja prymitywnej klasy opakowania na typ pierwotny (na przykład konwersja Integer na int ). Dzięki wprowadzeniu prymitywnych klas wrapperów oraz procesom autoboxingu i unboxingu , typy pierwotne są teraz pełnoprawnymi członkami Javy jako języka OOP. Przeglądanie pytań i odpowiedzi z rozmowy kwalifikacyjnej na stanowisko programisty Java.  Część 5 - 5Aby uzyskać bardziej dogłębną dyskusję na ten temat, gorąco polecam przeczytanie tego artykułu .

50. Co to jest klasa zagnieżdżona? Gdzie jest używany?

Klasa zagnieżdżona to klasa, która sama jest członkiem innej klasy. W Javie istnieją 4 rodzaje klas zagnieżdżonych: 1. Klasa wewnętrzna Ten rodzaj klasy jest deklarowany bezpośrednio w treści innej klasy. Klasa wewnętrzna jest niestatyczną klasą zagnieżdżoną i może uzyskać dostęp do dowolnego prywatnego pola lub metody instancji klasy zewnętrznej. Jako przykład stwórzmy zoo zawierające zwierzę — zebrę:
public class Zoo {
   class Zebra {
       public void eat(String food) {
           System.out.println("Zebra eats " + food);
       }
   }
}
Niezbyt skomplikowane, prawda? Przyjrzyjmy się przykładowi tworzenia instancji klasy wewnętrznej:
Zoo.Zebra zebra = new Zoo().new Zebra();
zebra.eat("apple");
Jak już widziałeś, konieczne jest najpierw utworzenie obiektu klasy otaczającej. Następnie używasz odniesienia do obiektu, aby utworzyć instancję klasy wewnętrznej. Chciałbym również zauważyć, że klasa wewnętrzna (niestatyczna klasa zagnieżdżona) nie może mieć metod statycznych ani pól statycznych. Dzieje się tak właśnie dlatego, że klasa wewnętrzna jest niejawnie powiązana z instancją jej klasy zewnętrznej i dlatego nie może deklarować w sobie żadnych metod statycznych. 2. Statyczne klasy zagnieżdżone Klasy te są podobne do poprzedniej kategorii, ale posiadają statyczny modyfikator dostępu w deklaracji klasy. Ponieważ tego rodzaju klasa nie ma dostępu do niestatycznych pól klasy zewnętrznej, wygląda bardziej jak statyczna część klasy zewnętrznej niż klasa wewnętrzna. Ale ta klasa ma dostęp do wszystkich statycznych elementów klasy zewnętrznej, nawet tych prywatnych. Przykład statycznej klasy zagnieżdżonej:
public class Zoo {
   static class Zebra {
       public void eat(String food) {
           System.out.println("Zebra eats " + food);
       }
   }
}
Tworzony jest w nieco inny sposób niż poprzedni:
Zoo.Zebra zebra = new Zoo.Zebra();
zebra.eat("apple");
Tutaj nie potrzebujemy obiektu klasy zewnętrznej, aby utworzyć obiekt statycznej klasy zagnieżdżonej. Wystarczy znać nazwę klasy zagnieżdżonej, aby znaleźć ją w klasie zewnętrznej. 3. Klasy lokalne Klasy lokalne to klasy zadeklarowane w treści metody. Obiekty klasy lokalnej można tworzyć i używać tylko w ramach metody otaczającej. Przykład:
public class Zoo {
   public void feed(String animal, String food) {
       switch(animal) {
           case "zebra":
               class Zebra {
                   public void eat(String food) {
                       System.out.println("Zebra eats " + food);
                   }
               }
               Zebra zebra = new Zebra();
               zebra.eat(food);
               ...
Oto przykład:
Zoo zoo = new Zoo();
zoo.feed("zebra", "apple");
Jeśli nie widziałbyś kodu metody Feed() , to nawet nie podejrzewałbyś, że istnieje klasa lokalna, prawda? Klasa lokalna nie może być statyczna ani przejściowa , ale może być oznaczona jako abstrakcyjna lub ostateczna (jedna LUB druga, ale nie oba, ponieważ jednoczesne użycie tych dwóch modyfikatorów powoduje konflikt). 4. Klasy anonimowe O klasach anonimowych mówiliśmy już powyżej i jak pamiętasz, można je tworzyć z dwóch źródeł — interfejsów i klas. Powody ich stosowania Używa się zagnieżdżonych klas statycznych i niestatycznych, ponieważ czasami lepiej jest osadzić małe klasy w bardziej ogólnych i trzymać je razem, aby miały większą spójność i wspólny cel. Zasadniczo klasy zagnieżdżone pozwalają zwiększyć hermetyzację kodu. Możesz zdecydować się na użycie klasy lokalnej, jeśli klasa jest używana wyłącznie w ramach jednej metody. Czy w takim przypadku musimy rozłożyć kod na aplikację? Nie. To powiedziawszy, dodam, że z mojego doświadczenia nigdy nie widziałem, żeby ktoś korzystał z zajęć lokalnych, ponieważ to, czy są one potrzebne, czy nie, jest wysoce kontrowersyjne. Możesz użyć klas anonimowych, gdy konkretna implementacja interfejsu lub klasy abstrakcyjnej jest potrzebna tylko raz. W takim przypadku nie ma potrzeby tworzenia osobnej, pełnoprawnej klasy z implementacją. Zamiast tego zachowaliśmy prostotę i zaimplementowaliśmy potrzebne metody, używając anonimowej klasy, użyliśmy obiektu, a następnie o nim zapomnieliśmy (oczywiście moduł zbierający elementy bezużyteczne nie zapomniał). Artykuł znajdujący się tutaj polepszy Twoje zrozumienie klas zagnieżdżonych.

51. Jakie modyfikatory dostępu może mieć klasa?

Istnieją różne typy klas i mają do nich zastosowanie różne modyfikatory dostępu:
  • klasa zewnętrzna może mieć modyfikator dostępu publicznego lub nie mieć go wcale (modyfikator domyślny);
  • klasa wewnętrzna (niestatyczna klasa zagnieżdżona) może mieć dowolny z 4 modyfikatorów dostępu;
  • zagnieżdżona klasa statyczna może mieć dowolny modyfikator dostępu, z wyjątkiem chronionego , ponieważ ten modyfikator implikuje dziedziczenie, co jest sprzeczne z jakimkolwiek statycznym elementem klasy (elementy statyczne nie są dziedziczone);
  • klasa lokalna może mieć tylko domyślny modyfikator (tzn. nie może mieć żadnego modyfikatora);
  • klasa anonimowa nie ma deklaracji klasy, więc nie ma w ogóle modyfikatora dostępu.
Na tym dzisiaj zakończymy. Do zobaczenia wkrótce!Przeglądanie pytań i odpowiedzi z rozmowy kwalifikacyjnej na stanowisko programisty Java.  Część 5 - 6
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION