Dlaczego w Javie nie ma funkcji Constant?

140

Próbowałem zidentyfikować powód istnienia stałych w Javie. Dowiedziałem się, że Java pozwala nam deklarować stałe za pomocą finalsłowa kluczowego.

Moje pytanie brzmi: dlaczego Java nie wprowadziła funkcji Constant ( const). Ponieważ wiele osób twierdzi, że pochodzi z C ++, w C ++ mamy constsłowo kluczowe.

Podziel się swoimi przemyśleniami.

gmhk
źródło
2
Nie jestconst słów kluczowych, ale nie ma bazowy cecha. Odpowiednio poprawiono tytuł i tagi.
Markiz Lorne

Odpowiedzi:

142

Za każdym razem, gdy przechodzę od ciężkiego kodowania C ++ do Javy, trochę czasu zajmuje mi przystosowanie się do braku stałej poprawności w Javie. To użycie constw C ++ różni się znacznie od deklarowania stałych zmiennych, jeśli jeszcze tego nie wiesz. Zasadniczo zapewnia to, że obiekt jest niezmienny, gdy uzyskuje się do niego dostęp za pomocą specjalnego rodzaju wskaźnika zwanego wskaźnikiem do stałej W Javie, w miejscach, w których normalnie chciałbym zwrócić wskaźnik do stałej, zamiast tego zwracam odwołanie z typem interfejsu zawierające tylko metody, które nie powinny mieć skutków ubocznych. Niestety, język nie wymusza tego.

Wikipedia oferuje następujące informacje na ten temat:

Co ciekawe, specyfikacja języka Java traktuje const jako zarezerwowane słowo kluczowe - tj. Takie, którego nie można używać jako identyfikatora zmiennej - ale nie przypisuje mu żadnej semantyki. Uważa się, że rezerwacja słowa kluczowego miała miejsce, aby umożliwić rozszerzenie języka Java o metody const w stylu C ++ i wskaźnik do typu const. Zgłoszenie prośby o ulepszenie w Java Community Process do implementacji poprawności const w Javie zostało zamknięte w 2005 roku, co oznacza, że ​​poprawność const prawdopodobnie nigdy nie znajdzie się w oficjalnej specyfikacji Java.

Rewolwerowiec47
źródło
10
Java finaljest jednak podobna.
reinierpost
62
Nie, nie jest. finalna przykład metoda działa zupełnie inaczej niż constmetody C ++ .
dom0
7
@reinierpost Słowo finalkluczowe we właściwościach lub zmiennych zapewnia tylko, że właściwość lub zmienna jest przypisana tylko raz . Nadal można by zmienić stan tego obiektu np. Wywołując jakąś metodę z efektami ubocznymi. finaljest trochę podobny do alokacji stosu w C ++ pod względem odwoływania się do obiektu, a nie wskaźnika, ale to wszystko. To oczywiście uzupełnienie tego, co już powiedział dom0.
Tim
9
finalw Javie wydaje się działać jak C ++ constdla typów wartości, ale bardziej jak C ++ non-const T&dla typów referencyjnych
Mark K Cowan
1
finał to schizofreniczne słowo kluczowe. Chociaż zapobiega ponownemu przypisaniu, jest również używany do ujawniania zmiennych domknięciom. Może chciałbym zapobiec ponownemu przypisaniu, ale nie ujawniać tych zmiennych, ale nie ma sposobu, aby to zrobić. Moim zdaniem jest to raczej słabo przemyślana funkcja językowa.
David Bradley,
82

Co to constznaczy
Po pierwsze, uświadom sobie, że semantyka słowa kluczowego „const” oznacza różne rzeczy dla różnych osób:

  • odwołanie tylko do odczytu - finalsemantyka języka Java - samej zmiennej odwołania nie można ponownie przypisać, aby wskazywała na inną instancję (lokalizację w pamięci), ale samą instancję można modyfikować
  • odwołanie tylko do odczytu - constwskaźnik C / semantyka odwołania - oznacza, że ​​tego odwołania nie można użyć do modyfikacji instancji (np. nie można przypisać do zmiennych instancji, nie można wywołać metod mutowalnych) - wpływa tylko na zmienną referencyjną, więc odwołanie inne niż const wskazujące na ta sama instancja może modyfikować instancję
  • obiekt niezmienny - oznacza, że ​​instancja nie może być modyfikowana - dotyczy instancji, więc żadne odwołanie inne niż stała byłoby niedozwolone lub nie można ich użyć do modyfikacji instancji
  • jakieś połączenie powyższych ?
  • inni ?

Dlaczego lub dlaczego nieconst
Po drugie, jeśli naprawdę chcesz zagłębić się w niektóre argumenty „za” i „przeciw”, zobacz dyskusję w ramach tego „błędu” prośby o wzmocnienie (RFE). Ten RFE wymaga funkcji „const” typu „tylko do odczytu”. Otwarty w 1999 r., A następnie zamknięty / odrzucony przez Sun w 2005 r., Temat "const" był intensywnie dyskutowany:

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4211070

Chociaż istnieje wiele dobrych argumentów po obu stronach, niektóre z często cytowanych (ale niekoniecznie przekonujących lub jednoznacznych) powodów przeciwko constobejmują:

  • może mieć mylącą semantykę, która może być niewłaściwie używana i / lub nadużywana (zobacz co constoznacza powyżej)
  • może powielać możliwości dostępne w inny sposób (np. projektowanie niezmiennej klasy, używanie niezmiennego interfejsu)
  • może być pełzanie cech, co prowadzi do konieczności wprowadzenia innych zmian semantycznych, takich jak obsługa przekazywania obiektów według wartości

Zanim ktokolwiek spróbuje ze mną debatować, czy są to dobre czy złe powody, zauważ, że to niemoje powody . Są po prostu „sednem” niektórych powodów, które uzyskałem, przeglądając dyskusję na temat RFE. Niekoniecznie się z nimi zgadzam - po prostu próbuję przytoczyć, dlaczego niektórzy ludzie (nie ja) mogą constuważać, że słowo kluczowe może nie być dobrym pomysłem. Osobiście chciałbym, aby więcej semantyki „const” zostało wprowadzonych do języka w sposób jednoznaczny.

Bert F.
źródło
2
+1 tylko za drugą część Twojej odpowiedzi. Wiele wielu słów kluczowych ma nietrywialną semantykę. Czy volatiletak łatwo jest zrozumieć? Albo final? Meh.
einpoklum
OTOH, Java została zaprojektowana tak, aby wykorzystywać jak najmniej z tych nietrywialnych funkcji. I nie mówię, że osiągnęli ten cel (lub że Java nie odeszła od tego celu). Ale wykluczenie go z tego powodu mogło nadal mieć wartość. To, że istnieją inne skomplikowane rzeczy, jest tym większym powodem, aby nie wprowadzać więcej (albo skończyłbyś z językiem D).
Maarten Bodewes
7

const w C ++ nie oznacza, że ​​wartość jest stałą.

const w C ++ oznacza, że ​​klient kontraktu zobowiązuje się nie zmieniać jego wartości.

To, czy wartość constwyrażenia zmienia się, staje się bardziej widoczne, jeśli jesteś w środowisku, które obsługuje współbieżność opartą na wątkach.

Ponieważ Java została zaprojektowana od samego początku do obsługi współbieżności wątków i blokad, nie spowodowało to zamieszania poprzez przeciążenie terminu w celu uzyskania semantyki, która finalma.

na przykład:

#include <iostream>

int main ()
{
    volatile const int x = 42;

    std::cout << x << std::endl;

    *const_cast<int*>(&x) = 7;

    std::cout << x << std::endl;

    return 0;
}

wyjścia 42, a następnie 7.

Chociaż xoznaczono jako const, ponieważ tworzony jest alias inny niż const, xnie jest stałą. Nie każdy kompilator wymaga volatiletego zachowania (chociaż każdy kompilator może wstawić stałą)

W bardziej skomplikowanych systemach otrzymujesz aliasy const / non-const bez użycia const_cast, więc nawyk myślenia, że ​​const oznacza, że ​​coś się nie zmieni, staje się coraz bardziej niebezpieczny. constoznacza po prostu, że twój kod nie może go zmienić bez rzutowania, a nie, że wartość jest stała.

Pete Kirkham
źródło
3
const int x = 42; - x jest stałą
2
@Neil Jeśli masz jeden obiekt lub zmienną z aliasami za pomocą wskaźników stałych i innych niż const, wówczas wartość aliasu stałego można zmienić za pomocą aliasu innego niż const. Dlatego constnie oznacza, że ​​wartość jest stała. Oznacza to, że klient wartości jest zmuszony nie modyfikować jej. W twoim przykładzie nie ma aliasu, więc wszyscy użytkownicy podlegają tym samym ograniczeniom. W ogóle tak nie jest. constwpływa na klientów, a nie na wartość - mówi, że nie możesz tego zmienić, nie że to się nie zmieni.
Pete Kirkham
1
Stała poprawność dotyczy tego, co programista powinien zrobić, a nie tego, co może zrobić . Myślę, że wszyscy macie ten punkt widzenia. Chciałem tylko dodać kilka centów, które mogą zainteresować czytelnika przyczynowego: wzorce projektowe takie jak immutable interfacei immutable objectto inny sposób (możliwy do pokonania za pomocą rzutowania i odbicia) na naśladowanie stałej w Javie. „True” const można wykonać za pomocą SealedObject , niestety niszczy to przypadek użycia naszego obiektu.
Martin Andersson,
6
Należy zauważyć, że wynik twojego programu jest nieokreślony. const_cast nie służy do zmiany zmiennych const, służy do przekazywania zmiennych const do interfejsów API, które nie są poprawne, ale także nie modyfikują wartości. Myślę, że nawyk myślenia, że ​​coś const się nie zmieni, jest dobry, ponieważ jeśli się zmienią, oznacza to, że twój program zawiera hacki, które mogą się zepsuć w dowolnym momencie w zależności od używanego kompilatora.
Cygon
1
Modyfikowanie wartości od urodzenia do stałej jest niezdefiniowanym zachowaniem. Twój dysk może być już sformatowany.
Zhe Yang
5

To trochę stare pytanie, ale pomyślałem, że i tak oddam moje 2 centy, ponieważ ten wątek pojawił się dzisiaj w rozmowie.

To nie odpowiada dokładnie, dlaczego nie ma stałej? ale jak uczynić swoje klasy niezmiennymi. (Niestety nie mam jeszcze wystarczającej reputacji, aby opublikować komentarz do zaakceptowanej odpowiedzi)

Sposobem na zagwarantowanie niezmienności obiektu jest staranne zaprojektowanie klas, aby były niezmienne. Wymaga to nieco więcej uwagi niż zmienna klasa.

To sięga wstecz do efektywnego elementu Java 15 Josha Blocha - Minimalizuj zmienność . Jeśli nie czytałeś książki, weź kopię i przeczytaj ją kilka razy. Gwarantuję, że poprawi to twoją figuratywną "grę java" .

W punkcie 15 Bloch sugeruje ograniczenie zmienności klas w celu zapewnienia stanu obiektu.

Aby bezpośrednio zacytować książkę:

Niezmienna klasa to po prostu klasa, której instancji nie można modyfikować. Wszystkie informacje zawarte w każdej instancji są dostarczane podczas jej tworzenia i są ustalane przez cały okres istnienia obiektu. Biblioteki platformy Java zawierają wiele niezmiennych klas, w tym String, zamknięte klasy pierwotne oraz BigInte- ger i BigDecimal. Istnieje wiele dobrych powodów: niezmienne klasy są łatwiejsze do zaprojektowania, zaimplementowania i używania niż klasy zmienne. Są mniej podatne na błędy i bezpieczniejsze.

Bloch następnie opisuje, jak uczynić swoje klasy niezmiennymi, stosując 5 prostych zasad:

  1. Nie podawaj żadnych metod modyfikujących stan obiektu (tj. Ustawiających, czyli mutatorów )
  2. Upewnij się, że klasa nie może zostać rozszerzona (oznacza to zadeklarowanie samej klasy jako final).
  3. Zrób wszystkie pola final.
  4. Zrób wszystkie pola private.
  5. Zapewnij wyłączny dostęp do wszelkich zmiennych komponentów. (wykonując obronne kopie obiektów)

Aby uzyskać więcej informacji, gorąco polecam zabrać ze sobą egzemplarz książki.

grego
źródło
3
const w C ++ jest DUŻO bardziej elastyczna niż niezmienność w pełnej skali. W pewnym sensie „const” można postrzegać jako „niezmienne w tym konkretnym kontekście”. Przykład: Mam klasę, która nie jest niezmienna, ALE chcę się upewnić, że nie jest modyfikowana za pośrednictwem niektórych publicznych interfejsów API. Stworzenie interfejsu (i zwrócenie go do tego publicznego API) zgodnie z sugestią Gunslinger47 daje to samo w Javie, ale chłopcze - jest brzydkie (i tak - jest ignorowane przez większość programistów Java, co prowadzi do znacznego niepotrzebnego bałaganu). ,
No-Bugs Hare
3

Semantyka języka C ++ constbardzo różni się od języka Java final. Gdyby projektanci go użyli const, byłoby to niepotrzebnie zagmatwane.

Fakt, że constjest to słowo zastrzeżone, sugeruje, że projektanci mieli pomysły na realizację const, ale od tamtej pory się na to nie zgadzają; zobacz ten zamknięty błąd . Podane przyczyny obejmują to, że dodanie obsługi stylu C ++ constspowodowałoby problemy ze zgodnością.

Stephen C.
źródło
-1

Istnieje sposób na tworzenie zmiennych „const” w Javie, ale tylko dla określonych klas. Po prostu zdefiniuj klasę z ostatecznymi właściwościami i podklasuj ją. Następnie użyj klasy bazowej, w której chciałbyś użyć „const”. Podobnie, jeśli potrzebujesz użyć metod „const”, dodaj je do klasy bazowej. Kompilator nie pozwoli ci modyfikować tego, co uważa za ostateczne metody klasy bazowej, ale odczyta i wywoła metody w podklasie.

user1122069
źródło
Czy możesz podać jakiś przykład?
NO_NAME
klasa MYString implementuje GetString {private final String aaaa; public String getString (); } klasa MutableString implementuje GetString {private String aaaa2; public String getString (); public String setString ()}
user1122069
-2

Istniałyby dwa sposoby definiowania stałych - consti static finalprzy użyciu tej samej semantyki. Ponadto static finallepiej opisuje zachowanie niżconst

Bozho
źródło
@Bozho, powiedziałeś lepsze zachowanie niż Const, jak to jest? czy możesz podać jakiś przykład
gmhk,
cóż, zmienna jest static(nie należy do konkretnej instancji) i final- nie można jej zmienić.
Bozho
-2

Możesz użyć statycznego finału, aby stworzyć coś, co działa podobnie do Const, użyłem tego w przeszłości.

protected static final int cOTHER = 0;
protected static final int cRPM = 1;
protected static final int cSPEED = 2;
protected static final int cTPS = 3;
protected int DataItemEnum = 0;

public static final int INVALID_PIN = -1;
public static final int LED_PIN = 0;
Hamish
źródło
Negowany za optymalizację opartą na plotkach, ponieważ słyszałem plotkę, że jest to nieskuteczna strategia.
afarley
Usunąłem plotki z odpowiedzi. nadal możesz używać static final int do tworzenia kodu w stylu const.
hamish
Ok, wycofałem swój głos przeciw. Być może niektóre inne głosy przeciwne dotyczą oświadczenia o przełączniku (co to ma wspólnego z resztą twojego przykładu?)
afarley.
w instrukcji switch użyłem cRPM tak, jakby to była stała. całkiem dobrze, biorąc pod uwagę powyższe. więc tak, usunąłem przełącznik.
hamish