C ma wskaźniki, a Java ma tak zwane referencje. Mają pewne wspólne cechy w tym sensie, że wszystkie na coś wskazują. Wiem, że wskaźniki w C przechowują adresy, na które wskazują. Czy referencje przechowują również adres? Czym się różnią, tyle że wskaźnik jest bardziej elastyczny i podatny na błędy?
97
final
Odwołanie w Javie jest prawie równoważne odwołaniu do C ++. Powodem, dla którego nie są dokładnie równoważne, jest to, że odwołanie do C ++ nie jest również zerowalne, podczas gdyfinal
odwołanie w Javie jest zerowalne.Odpowiedzi:
Referencje można zaimplementować, przechowując adres. Zazwyczaj odniesienia do Java będą implementowane jako wskaźniki, ale nie jest to wymagane przez specyfikację. Mogą używać dodatkowej warstwy pośredniej, aby ułatwić zbieranie śmieci. Ale ostatecznie (prawie zawsze) sprowadza się do wskaźników (w stylu C) zaangażowanych w implementację odniesień (w stylu Java).
Nie można wykonywać arytmetyki wskaźników za pomocą referencji. Najważniejszą różnicą między wskaźnikiem w C a referencją w Javie jest to, że nie można faktycznie uzyskać (i manipulować) wartości bazowej referencji w Javie. Innymi słowy: nie można wykonywać arytmetyki wskaźników.
W C możesz dodać coś do wskaźnika (tj. Adres) lub odjąć coś, aby wskazać rzeczy „w pobliżu” lub wskazać miejsca, które są w dowolnym miejscu.
W Javie odwołanie wskazuje tylko na jedną rzecz. Możesz sprawić, by zmienna zawierała inne odwołanie, ale nie możesz po prostu poprosić o wskazanie „rzecz po rzeczy oryginalnej”.
Referencje są mocno wpisane. Inną różnicą jest to, że typ odwołania jest znacznie bardziej ściśle kontrolowany w Javie niż typ wskaźnika w C. W C możesz mieć
int*
i rzutować nachar*
ai po prostu ponownie interpretować pamięć w tym miejscu. Ta reinterpretacja nie działa w Javie: możesz interpretować obiekt na drugim końcu referencji jako coś, co już jest (tzn. Możesz rzutowaćObject
referencję naString
referencję tylko wtedy, gdy wskazany obiekt to aString
).Różnice te sprawiają, że wskaźniki C są silniejsze, ale także bardziej niebezpieczne. Obie te możliwości (arytmetyka wskaźnika i reinterpretacja wskazywanych wartości) zwiększają elastyczność C i są źródłem pewnej potęgi języka. Ale są również dużymi źródłami problemów, ponieważ jeśli użyte nieprawidłowo, mogą łatwo złamać założenia, na których opiera się Twój kod. I jest to dość łatwe w użyciu ich nieprawidłowo.
źródło
memcpy
przeniesienie jednego do achar[]
) i odwrotnie. Jeśli wskaźnik zostanie przekonwertowany na ciąg liczb, który jest przechowywany w innym miejscu (być może pokazany na ekranie i skopiowany przez operatora na kartce papieru), wszystkie kopie wskaźnika w komputerze zostaną zniszczone, a ta sekwencja liczb zostanie przekonwertowana wracając do wskaźnika (być może po wpisaniu przez operatora), wskaźnik nadal musi wskazywać to samo, co wcześniej. Program, który ...Referencje w C ++ są znowu różne.
Muszą być zainicjowane i nie mogą mieć wartości zerowej (przynajmniej nie w dobrze uformowanym programie) i nie mogą być ponownie ustawione, aby odwoływać się do czegoś innego. Odwołanie do C ++ jest znacznie bardziej jak alias obiektu.
Inną ważną różnicą między wskaźnikami a referencjami Java / C ++ jest to, że możesz wziąć adres wskaźnika, do którego nie możesz uzyskać dostępu do adresu referencji (w rzeczywistości referencja C ++ wcale nie musi istnieć jako obiekt w pamięci), w związku z czym możesz mieć wskaźnik do wskaźnika, ale nie odniesienie do odniesienia
źródło
Referencje Java i wskaźniki C różnią się dokładnie dwoma punktami:
char
,int
i tak dalej).Ktoś napisał, że odwołania są mocno wpisane, ponieważ nie można zmusić kompilatora do traktowania
int*
jako plikuchar*
.Całkowicie pomijając fakt, że ta konkretna konwersja jest rzeczywiście bezpieczna , nie ma polimorfizmu w C, więc porównanie nie jest początkowe.
Z pewnością Java jest silniej typowana niż C, nie dlatego, że jest to cecha wskaźników C w porównaniu z referencjami Java, musisz użyć JNI do złamania bezpieczeństwa typu (oprócz ignorowania ogólnych ograniczeń), ale nawet w C musisz wymusić kompilator.
Ktoś napisał, że odniesienia Java może być realizowany jako wskaźniki C, do których mówię na pewno, ponieważ są one ściśle mniej wydajne, na maszynach 32bit one zazwyczaj są, jeśli JVM jest realizowany w C . Chociaż na maszynach 64 - bitowych są one zwykle skompresowanymi wskaźnikami zwykłych obiektów („skompresowanymi operacjami OOP”) w celu zaoszczędzenia miejsca i przepustowości.
W każdym razie te wskaźniki C nie muszą być równoważne adresom sprzętowym, nawet jeśli zazwyczaj (> 99% implementacji) są spowodowane wydajnością.
Wreszcie jest to szczegół implementacji, który nie jest ujawniany programistom.
źródło
Są nieco inne. W Javie kopia odwołania jest kopiowana na stos wywoływanej funkcji, wskazując ten sam obiekt co funkcję wywołującą i umożliwiając manipulowanie tym obiektem. Nie można jednak zmienić obiektu, do którego odnosi się funkcja wywołująca.
Rozważ następujący kod Java
Rozważmy teraz wskaźnik w c ++:
źródło