JavaRush /Blog Java /Random-PL /Różnice pomiędzy konstruktorami a metodami zwykłymi.
fog
Poziom 18

Różnice pomiędzy konstruktorami a metodami zwykłymi.

Opublikowano w grupie Random-PL
Konstruktor to specjalna metoda, która ma na celu wstępne ustawienie wartości pól obiektu. Na pierwszy rzut oka konstruktory obiektów nie różnią się zbytnio od zwykłych metod obiektowych. I rzeczywiście, wewnątrz konstruktora możemy zrobić wszystko, co możemy zrobić w zwykłych metodach obiektowych: wyprowadzić tekst do konsoli, uzyskać dostęp do wszystkich pól i metod nowego obiektu, zgłosić wyjątki i tak dalej. Podobnie jak zwykłe metody, konstruktory mogą mieć argumenty. Podobnie jak metody przeciążone, może istnieć kilka konstruktorów z różnymi sygnaturami. Podobnie jak metody generyczne, konstruktory można parametryzować za pomocą zmiennych typu. Nawet jeśli zajrzymy do kodu bajtowego wygenerowanego przez kompilator, to w miejscu, w którym powinno znajdować się wywołanie konstruktora, znajdziemy wywołanie jakiejś metody, której nazwa nie różni się od wywołania innych <init>metod obiekt. A po znalezieniu kodu bajtowego tej metody przekonamy się, że zawiera on wynik kompilacji naszego konstruktora. Wydaje się, że nie ma wielu różnic w stosunku do metod konwencjonalnych, ale istnieją i to dość znaczące. Najpierw zastanówmy się, dlaczego właściwie potrzebujemy konstruktorów? Aby przechowywać i przetwarzać dowolne dane, czy to typy pierwotne, tablice, czy obiekty, potrzebujemy określonej ilości pamięci. Mogą to być rejestry procesora, przestrzeń stosu, fragment przestrzeni przydzielony w sekcji danych procesowych lub w dynamicznie alokowanej części pamięci (stercie). W wielu językach programowania, w celu przyspieszenia, gdy program żąda nowego fragmentu pamięci, pamięć jest przekazywana programowi nieczyszczona i może zawierać dowolne dane, które były wcześniej przechowywane w tej komórce pamięci. Przygotowanie i zapisanie niezbędnych wartości w takim kawałku pamięci, aby w efekcie końcowym powstała tam jakaś sensowna struktura danych, spadło całkowicie na barki programisty. Całkiem naturalnie programiści chcieli ułatwić sobie życie i napisali procedury inicjujące (to znaczy ustawiające wartości początkowe) często używanych struktur danych. Takie procedury były używane niemal stale, dlatego twórcy języka Java postanowili wprowadzić obowiązkowe wywoływanie takich procedur inicjujących podczas tworzenia obiektów i nazwali je konstruktorami . Kiedy w Javie tworzony jest nowy obiekt, dzieje się co następuje: Najpierw menedżer pamięci Java przydziela ilość pamięci niezbędną do umieszczenia obiektu. W tym przypadku pod uwagę brane są nie tylko pola zadeklarowane bezpośrednio w klasie tworzonego obiektu, ale także pola zadeklarowane we wszystkich przodkach tej klasy. Dodatkowo w woluminie tym znajduje się miejsce na umieszczenie struktur wykorzystywanych przez maszynę Java na potrzeby wewnętrzne. Wszystkie pola takiego „pustego” automatycznie ustawiane są na wartości domyślne – nulldla typów referencyjnych, 0dla liczb i falsedlaboolean. Następnie automatycznie wywoływany jest konstruktor klasy, którego zadaniem jest ustawienie początkowych wartości pól obiektu. O ile w normalnej metodzie pierwszą instrukcją może być cokolwiek, konstruktor ma znacznie mniej swobody. Pierwsza instrukcja konstruktora musi być jawnym wywołaniem innego konstruktora tej samej klasy albo jawnym lub niejawnym wywołaniem konstruktora klasy nadrzędnej. Jawne wywołania konstruktorów tej samej klasy są wykonywane przy użyciu słowa kluczowego, thispo którym następuje zestaw argumentów ujętych w nawiasy. Wywołanie konstruktora klasy nadrzędnej odbywa się dokładnie w ten sam sposób, z tą różnicą, że używane jest słowo kluczowe super. W argumentach jawnego wywołania konstruktora tej samej lub nadrzędnej klasy nie można uzyskać dostępu do pól i metod obiektu, a także użyć słów kluczowych thisi super, ponieważ jawne wywołanie konstruktora wprowadza kontekst statyczny. Aby niejawnie wywołać konstruktor klasy nadrzędnej, nie trzeba nic pisać, ale domyślnie wywoływany jest konstruktor domyślny, który musi istnieć i być widoczny dla bieżącej klasy. Jednocześnie należy mieć na uwadze, że jeśli łańcuch wywoływania konstruktorów-rodziców zostanie przerwany zanim konstruktor klasy Objectznajdujący się na górze łańcucha pomyślnie zakończy swoją pracę, to obiektu nie będzie można sfinalizować, czyli metody finalize()takiego obiektu nigdy nie zostanie wywołane. Po zakończeniu działania konstruktora klasy nadrzędnej kontrola jest niejawnie przekazywana do bloków inicjatorów instancji i inicjatorów pól instancji bieżącej klasy. Inicjatory są wykonywane w kolejności, w jakiej pojawiają się w tekście programu. Dopiero gdy inicjatory zakończą swoją pracę, kontrola zostaje przekazana reszcie konstruktora. Pozostałe cechy konstruktorów odnoszą się do modelu pamięci Java. Jeśli klasa lub jeden z jej przodków zastąpi metodę finalize(), wówczas zakończenie działania konstruktora nastąpi przed ( zdarza się-przed ) uruchomieniem metody finalize(). Jeśli jakikolwiek wątek zobaczył referencję do obiektu po zakończeniu działania konstruktora, to gwarantuje się, że wątek ten zobaczy poprawnie zainicjowane final-pola obiektu, którego inicjalizacja nastąpiła przed zakończeniem konstruktora.
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION