2013-02-04 12 views
27

Poproszono mnie to pytanie w wywiadzie ostatnio:Klasy końcowe w Javie, które nie powinny być ostateczne lub odwrotnie?

Możesz nazwać każdą klasę w Java API, które jest końcowy, który nie powinien być albo taki, który nie jest i powinno być "?

Nie mogłem wymyślić żadnego. To pytanie sugeruje, że powinienem znać wszystkie klasy API, takie jak tył mojej ręki, czego osobiście nie oczekiwałbym od żadnego programisty Java.

Jeśli ktokolwiek zna takie klasy, proszę podać przykłady.

+2

Prawdopodobnie test dotyczy Twojego doświadczenia z API Java, nie oznacza to, że powinieneś o nim wiedzieć. – Bogdan

+3

W niektórych punktach, głównie podczas debugowania okropnego kodu, sugerowałbym, że 'Obiekt' powinien być ostateczny. –

+3

Nie wyjaśniłeś, jakie pytanie chcesz zadać. Szukasz przykładu lub opinii na temat pytania do wywiadu? –

Odpowiedz

21

pierwszych przykładów, które przychodzą na myśl, to tylko niektóre z nieostatecznej podklasy numer, taki jak BigDecimal i BigInteger, które prawdopodobnie powinny być ostateczne.

W szczególności wszystkie z ich metod można przesłonić. To pozwala na tworzenie złamaną BigDecimal, na przykład:

public class BrokenBigDecimal extends BigDecimal { 
    public BigDecimal add(BigDecimal augend) { 
     return BigDecimal.ZERO; 
    } 
}  

że może stworzyć poważne problemy, jeśli otrzyma BigDecimal z kodem niezaufane na przykład.

Parafrazując Effective Java:

  • Projekt i dokument do dziedziczenia albo zakazać go
  • Ćwiczenia powinny być niezmienne, chyba że jest to bardzo dobry powód, aby uczynić je zmienny
+1

+1 java.math.BigInteger też –

+0

docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html –

+1

Możesz zaprojektować zepsutą listę/kolekcję/etc, BigDecimal, BigInteger są ok nie są ostateczne imo. Możesz je śledzić, jeśli chcesz. Bycie ostatecznym nic nie pomoże w ich przypadku. – bestsss

-2

Sprawdź klasę String, która jest ostateczna i prawdopodobnie powinna być twoją odpowiedzią w wywiadzie.

Sprawdź dokumenty.

http://docs.oracle.com/javase/7/docs/api/java/lang/String.html

+7

Dlaczego powinno to być * nie * końcowe? –

+1

Cóż, .NET's ['String'] (http://msdn.microsoft.com/en-us/library/system.string.aspx) jest * również * końcowy * i * niezmienny, jak Java. –

+1

Z ciekawości; jaki byłby twój powód, aby twierdzić, że nie powinna być ostateczna? Odkąd mówisz, że jest _obvious_. ;) –

22

java.awt.Dimension ISN” t ostateczne lub niezmienne i powinno być. Wszystko, co zwróci Wymiar (np. Obiekt Window), musi wykonać obronne kopie, aby uniemożliwić osobom dzwoniącym robienie nieprzyjemnych rzeczy.

+0

To nie jest niezmienne ze względu na dawne czasy, tworzenie nowych obiektów (a następnie GC) nie było dokładnie tanie, podobnie jak Point/Rectangle. Te klasy powinny być podobne, ale w chwili obecnej java nie ma takiego przepisu. – bestsss

+0

Niestety była to nieprawidłowa optymalizacja. Pozostawienie go zmiennym oznaczało konieczność tworzenia defensywnych kopii, które pozostawiają zwiększoną alokację/śmieci nie mniej. –

+0

Jak to zrobić? przekazałeś wymiar jako parametr, to był pomysł. Również kopie są potrzebne tylko do kodu przestrzeni klienta, wewnątrz obiektu, do którego dostęp mają jego pola (bez kopii). Nie bronię jednak opuszczania publicznych pól wymiaru, chociaż ... po prostu wyjaśnianie - sprawienie, by było ostateczne, nie pomogłoby samo w sobie. – bestsss

3

Moim zdaniem, odpowiedź powinna być taka, że ​​jest to kwestia gustu, której zajęcia powinny być ostateczne, a które nie.

Istnieją uzasadnione powody, aby Integer, Double i String wszystkie final.

Istnieją powody, aby narzekać na to.

Następnie jest BitSet, BitInteger itp., Które można wykonać final.

Istnieje kilka sytuacji, w których zajęcia nie są final, ale nie można ich również rozszerzyć w rozsądny sposób, więc prawdopodobnie powinny być ostateczne.

Aby wybrać konkretną klasę: BitSet. Nie jest to final, ale nie można go rozszerzyć, aby dodać nieco operacji shift.Równie dobrze mogliby to uczynić final lub pozwolić nam dodać taką funkcjonalność.

+0

Nie sądzę, że to tylko kwestia gustu - Wiele cech bezpieczeństwa języka programowania Java zależy od tego, czy obiekty String są na przykład niezmienne. A jeśli chcesz zmienności, masz zmienną klasę towarzyszącą, StringBuilder. – assylias

+0

@assylias Powiedziałem, że istnieją dobre powody, aby mieć 'String'' final' ... –

1

Klasa schodzi z klasy Date. Jest to zmienna, prosta klasa wartości (zasadniczo owijająca się wokół long), ale dobrą heurystyką jest to, że proste klasy wartości powinny być niezmienne. Zwróć także uwagę na liczne nieużywane metody: więcej dowodów na to, że projekt został spartaczony. Zmienność parametru Date to a source of bugs, requiring disciplined defensive copying.

+0

Zobacz także: http://stackoverflow.com/a/187314/545127 – Raedwald

+0

Klasa danych jest podświetlona przez java.sql.Date/Time/Znacznik czasu, jako ostateczny, nie pomoże, ponieważ ma metody ustawiające. Właściwie bycie nieostatnim jest dobre, ponieważ możesz przesłonić ustawiające i rzucić UnsupportedOperationException, czyniąc klasę niezmienną. – bestsss

+0

@bestsss "ponieważ ma metody setera": chodzi o to, że 'Date' nie powinno mieć metod setera. – Raedwald

0

taki, który nie jest i powinno być

Większość końcowych klas w Javie są tak zaprojektowane, z powodu w/względy bezpieczeństwa na uwadze, ogólnie istnieje stosunkowo niewiele z nich ostateczne. Na przykład java.util.String jest ostateczny z tego właśnie powodu. Tak samo jest z wieloma innymi. Niektóre klasy w/prywatny c-tor są deklarowane jako ostateczne (Math, StrictMath), ale nie ma to znaczenia w takim przypadku.

Zasadniczo, jeśli nie ma problemów z bezpieczeństwem, nie obchodzi mnie, czy klasa jest ostateczna, ale zawsze można użyć niepublicznego c-tor w/niektórych fabryk, skutecznie ograniczając zdolność do podklasy. Zwykle jest to mój preferowany sposób, ponieważ umożliwia podklasowanie pakiet-prywatne.

W skrócie: Nie mogę wymyślić ostatecznej klasy, która nie powinna być, jednak są takie, które potencjalnie mogłyby być. Na przykład: java.lang.Thread jako ostateczna może nie potrzebować ochrony przed złośliwym clone().

Powiązane problemy