2013-02-04 6 views
27

Mi è stato chiesto a questa domanda in un'intervista recente:Classi finali in Java che non dovrebbero essere definitive o viceversa?

Potete chiamare qualsiasi classe nella API Java che è definitiva che non dovrebbe essere o uno che non è e non dovrebbe essere '?

Non riuscivo a pensare a nessuno. La domanda implica che dovrei conoscere tutte le classi API come il palmo della mia mano, che personalmente non mi aspetterei di conoscere da nessuno sviluppatore Java.

Se qualcuno conosce tali classi, si prega di fornire esempi.

+2

Probabilmente il test riguarda la tua esperienza con l'API Java, non significa che dovresti conoscerlo a memoria. – Bogdan

+3

In alcuni punti, principalmente durante il debug di codice orribile, suggerirei che 'Object' avrebbe dovuto essere reso definitivo. –

+3

Non hai chiarito quale domanda vuoi chiedere. Stai cercando un esempio o un'opinione sulla domanda dell'intervista o altro? –

risposta

21

I primi esempi che vengono in mente sono alcune delle sottoclassi numerici non definitive, come ad esempio BigDecimal e BigInteger, che dovrebbe probabilmente essere stato finale.

In particolare, tutti i loro metodi possono essere sostituiti. Che consente di creare una rotta BigDecimal, ad esempio:

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

che potrebbero creare problemi significativi se si riceve BigDecimal da un codice non attendibile per esempio.

parafrasando Effective Java:

  • Progettazione e documento per eredità o altrimenti vietare
  • classi dovrebbero essere immutabili a meno che non ci sia una buona ragione per farli mutevole
+1

+1 java.math.BigInteger anche –

+0

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

+1

È possibile progettare la lista/raccolta/ecc., BigDecimal, BigInteger non è ok imo. Puoi seguirli se vuoi. Essere finalisti non aiuterà nulla nel loro caso. – bestsss

-2

Controlla la classe String che è definitiva e probabilmente avrebbe dovuto essere la tua risposta nell'intervista.

Controllare i documenti.

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

+7

Perché dovrebbe essere * non * definitivo? –

+1

Bene, .NET ['String'] (http://msdn.microsoft.com/en-us/library/system.string.aspx) è * anche * definitivo * e * immutabile, come Java. –

+1

Per curiosità; quale sarebbe il tuo ragionamento per dire che non dovrebbe essere definitivo? Dal momento che dici che è _obvious_. ;) –

22

java.awt.Dimension isn' t finale o immutabile e avrebbe dovuto essere. Tutto ciò che restituisce una dimensione (ad esempio un oggetto Window) deve fare copie difensive per impedire ai chiamanti di fare cose cattive.

+0

Non è immutabile a causa dei vecchi tempi, la creazione di nuovi oggetti (e il successivo GC) non era esattamente economico, allo stesso modo Punto/Rettangolo. Queste classi dovrebbero essere simili al valore, ma al momento java mancano di tale disposizione. – bestsss

+0

Sfortunatamente si trattava di un'ottimizzazione non valida. Lasciandolo mutabile significava la necessità di creare copie difensive che lasciano una maggiore allocazione/immondizia non inferiore. –

+0

In che modo? tu passi la dimensione come parametro, questa era l'idea. Anche le copie sono necessarie solo per il codice spazio client, all'interno del awt l'oggetto è accessibile dai suoi campi (nessuna copia). Non difendo lasciando campi di dimensione pubblici, anche se ... solo spiegando - renderlo definitivo non avrebbe aiutato da solo. – bestsss

3

A mio parere, la tua risposta avrebbe dovuto essere che è una questione di gusti quali classi devono essere definitive e quali no.

Ci sono buoni motivi per rendere Integer, Double e String tutti final.

Ci sono buone ragioni per lamentarsi di questo.

Quindi c'è BitSet, BitInteger ecc. Che potrebbe essere effettuato final.

Ci sono un certo numero di situazioni in cui le classi non sono final, ma non possono anche essere estese ragionevolmente, quindi probabilmente avrebbero dovuto essere rese definitive.

Per selezionare una classe particolare: BitSet. Non è final, ma non è possibile estenderlo per aggiungere un po 'di operazione shift.Potrebbero anche averlo fatto, final, o permetterci di aggiungere tale funzionalità.

+0

Non penso sia solo una questione di gusti: molte funzionalità di sicurezza del linguaggio di programmazione Java dipendono, ad esempio, dagli oggetti String immutabili. E se vuoi la mutabilità, hai la classe companion mutabile, StringBuilder. – assylias

+0

@assylias Ho detto che ci sono buoni motivi per avere 'String'' final' ... –

1

La classe Date esce. È una classe di valori semplice mutabile (essenzialmente un wrapper attorno a un long), ma una buona euristica è che le classi di valori semplici dovrebbero essere immutabili. Notare anche i suoi numerosi metodi deprecati: più prove del fatto che il design è fallito. La mutabilità di Date è a source of bugs, requiring disciplined defensive copying.

+0

Vedi anche: http://stackoverflow.com/a/187314/545127 – Raedwald

+0

La classe dati viene sublocata da java.sql.Date/Time/Timestamp, essendo finale non sarà d'aiuto in quanto ha metodi di setter. In realtà essere non-final è buono in quanto puoi scavalcare i setter e lanciare UnsupportedOperationException, rendendo la classe immutabile. – bestsss

+0

@bestsss "come ha i metodi di setter": il punto è, 'Data' non dovrebbe avere metodi setter. – Raedwald

0

uno che non è e dovrebbe essere

La maggior parte delle classi finali in Java sono progettati in modo da causa w/considerazioni di sicurezza in mente, nel complesso ci sono relativamente pochi quelli finali. Ad esempio, java.util.String è definitivo proprio per questo motivo. Così sono molti altri. Alcune classi con c-tor privato sono dichiarate finali (Math, StrictMath) ma non importa in questo caso.

Fondamentalmente, a meno che non ci siano problemi di sicurezza, non mi interessa se la classe è definitiva, ma puoi sempre usare il c-tor non pubblico con qualche fabbrica, limitando efficacemente la possibilità di sottoclasse. Di solito è il mio modo preferito in quanto consente la sottoclasse di pacchetti-privati.

In breve: non riesco a pensare a una classe finale che non dovrebbe essere, tuttavia ce ne sono alcuni che potrebbero potenzialmente essere stati. Ad esempio, java.lang.Thread in fase finale potrebbe non aver avuto bisogno di proteggere contro il dannoso clone().

Problemi correlati