Perché Java ha metodi "void"?

52

Fa / perché Java ha bisogno di avere metodi void ? Riferimento :

Any method declared void doesn't return a value.

Per quanto posso pensare, ogni utilizzo di void sarebbe meglio se restituissi un flag di stato, l'oggetto invocato o null .

Ciò renderebbe ogni chiamata un'asserzione che è assegnabile e faciliterebbe i modelli di builder e il concatenamento dei metodi. I metodi che vengono invocati solo per i loro effetti in genere restituiscono un valore booleano o generico Success o generano un'eccezione in caso di errore.

    
posta marisbest2 24.04.2017 - 16:09
fonte

9 risposte

159

Perché c'è una differenza tra "Questa funzione può avere successo o fallire ed è abbastanza consapevole che può dire la differenza" e "Non c'è feedback sull'effetto di questa funzione." Senza void , controlli infinitamente i codici di successo e credi di scrivere un software robusto, quando in realtà non stai facendo nulla del genere.

    
risposta data 24.04.2017 - 16:19
fonte
96
  1. Perché C ha un tipo void e Java è stato progettato per seguire molte delle convenzioni della famiglia di linguaggio C.
  2. Ci sono molte funzioni a cui non vuoi restituire un valore. Che cosa hai intenzione di fare con "un generico Success tipo" comunque? Infatti, i valori di ritorno per indicare il successo sono ancora meno importanti in Java rispetto a C, perché Java ha delle eccezioni per indicare un errore e C no.
risposta data 24.04.2017 - 16:14
fonte
65

Il motivo originale per cui la lingua ha un tipo void è perché, come in C , i creatori del linguaggio non volevano complicare inutilmente la sintassi della lingua con procedura s e funzione come ha fatto Pascal.

Questa era la ragione originale.

I tuoi suggerimenti:

returning a status flag

Questo è un no-no. Non usiamo flag di stato. Se qualcosa va storto, lo segnaliamo tramite eccezioni.

the object being invoked

Lo stile fluente delle invocazioni è uno sviluppo recente. Molti dei programmatori che oggi stanno usando molto volentieri fluentemente e alzano gli occhi se mai devono usare un'interfaccia che non lo supporta non sono nati nemmeno quando è stato creato Java.

returning null

Questo ti costringerebbe a dichiarare un metodo come restituire qualcosa, quando in realtà non restituisce nulla, quindi sarebbe molto confuso per qualcuno che sta guardando un'interfaccia cercando di capire cosa fa. La gente inventerebbe inevitabilmente una classe altrimenti inutile che sta per "nessun valore di ritorno" in modo che tutte le funzioni che non hanno nulla da restituire possano restituire un riferimento nullo a tale classe. Quello sarebbe goffo. Fortunatamente, c'è una soluzione a questo, si chiama void . E questa è la risposta alla tua domanda.

    
risposta data 24.04.2017 - 21:07
fonte
20

Alcuni metodi, come System.out.println , non restituiscono nulla di utile, ma sono chiamati esclusivamente per questo effetto collaterale. void è un utile indicatore per il compilatore e per il lettore di codice che non restituisce alcun valore utile.

Restituire null anziché void significa che si otterrebbe solo una NullPointerException nel momento in cui si utilizza questo valore per qualsiasi cosa. Quindi scambiate un errore di compilazione per un errore di runtime che è peggio. Inoltre, dovresti definire il tipo di ritorno come Object , che sarebbe fuorviante e confuso. (E il concatenamento non funzionerebbe ancora.)

I codici di stato vengono solitamente utilizzati per indicare condizioni di errore, ma Java ha eccezioni a questo scopo.

Il ritorno di this non è possibile dai metodi statici.

Il ritorno di un oggetto generico Success non avrebbe alcun scopo utile.

    
risposta data 24.04.2017 - 21:48
fonte
11

Una ragione è che può essere fuorviante restituire sempre qualcosa di diverso da, diciamo, null . Esempio:

Che cosa dovrebbe restituire Arrays.sort(a) ?

Se sostieni che a deve essere restituito in modo che la chiamata possa essere concatenata (che sembra essere la tua risposta a giudicare dalla tua domanda), allora non è più chiaro se il valore di ritorno è una copia dell'oggetto originale o dell'oggetto originale stesso. Entrambi sono possibili. E sì, potresti metterlo nella documentazione, ma è abbastanza ambiguo che non dovresti creare l'ambiguità in primo luogo.

D'altro canto, se si sostiene che null debba essere restituito, si pone la domanda su quali informazioni il valore di ritorno è in grado di fornire al chiamante e perché il programmatore dovrebbe essere costretto a scrivere return null quando trasmette nessuna informazione.

E se restituisci qualcos'altro totalmente assurdo (come la lunghezza di a ), allora rende semplicemente l'uso di quel valore di ritorno davvero confuso - pensa solo quanto più confuso è dire int len = Arrays.sort(a) invece di int len = A.length !

    
risposta data 26.04.2017 - 01:46
fonte
7

Restituire un boolean che è sempre uguale a true che suggerisci, non è solo privo di senso (il valore di ritorno non ha informazioni), ma in realtà sarebbe fuorviante. La maggior parte delle volte, è meglio usare i tipi di ritorno che portano solo quante informazioni sono effettivamente disponibili - ecco perché in Java hai boolean per true / false invece di restituire un int con 4 miliardi possibili valori. Allo stesso modo, restituire un boolean con due valori possibili in cui esiste un solo valore possibile ("successo generico"), sarebbe fuorviante.

Inoltre, aggiungerebbe un sovraccarico di prestazioni non necessario.

Se un metodo viene utilizzato solo per il suo effetto collaterale, non c'è nulla da restituire, e il tipo di ritorno void riflette esattamente questo. Potenziali errori rari possono essere segnalati tramite eccezioni.

Una cosa che potrebbe essere migliorata, renderebbe void un tipo effettivo, come Unit di Scala. Questo risolverebbe alcuni problemi come gestire i generici.

    
risposta data 24.04.2017 - 19:12
fonte
4

Java è una lingua relativamente vecchia. E nel 1995 (quando fu creato) e poco dopo i programmatori erano molto preoccupati della quantità di tempo che un processo prendeva il controllo del processore e del consumo di memoria. Restituire void eliminerebbe alcuni cicli di clock e un po 'di consumo di memoria da una chiamata di funzione perché non dovresti mettere il valore di ritorno nello stack e non dovresti successivamente rimuoverlo.

Il codice efficiente non ti restituisce qualcosa che non utilizzeresti mai, e quindi mettere il vuoto in qualcosa che ha un valore di ritorno privo di significato è una pratica molto migliore che non restituire un valore di successo.

    
risposta data 24.04.2017 - 19:12
fonte
2

Ho letto argomenti che suggeriscono che la seconda opzione (return this ) dovrebbe essere l'approccio al posto di void . Questa è una buona idea, ma l'approccio in stile costruttore non era popolare al momento della creazione di Java. Se fosse così popolare in quel momento come ora, quello potrebbe essere stato l'approccio adottato. Restituire null è una pessima idea IMO. Vorrei che null non fosse nemmeno nella lingua.

Il problema ora è che se un metodo restituisce un'istanza del proprio tipo, non è chiaro se si tratti di un nuovo oggetto o dello stesso. Spesso non importa (o non dovrebbe) importa ma altre volte importa. Suppongo che il linguaggio possa essere modificato per restituire implicitamente this sui metodi void. L'unico problema che mi viene in mente al momento è che se il metodo è stato successivamente modificato per restituire un nuovo oggetto dello stesso tipo, non ci sarebbero stati avvisi di compilazione, ma forse non è un grosso problema. L'attuale tipo di sistema non si cura di questi tipi di modifiche ora. Il modo in cui questo interagisce con l'ereditarietà / le interfacce richiederebbe una certa considerazione, ma consentirebbe alle vecchie API senza uno stile builder di essere facilmente richiamate come se lo fossero.

    
risposta data 24.04.2017 - 18:36
fonte
2

Un altro aspetto:

Java è un linguaggio statico con caratteristiche piuttosto severe. Ciò significa che molte cose che sarebbero piuttosto aperte o dinamiche in altre lingue (c / f Ruby, Lisp ecc.) Sono rigorosamente determinate.

Questa è una decisione di progettazione generale. Il "perché" è difficile da rispondere (beh, perché i progettisti del linguaggio pensavano che sarebbe stato bello!). Il "cosa per" è abbastanza chiaro: consente al compilatore di rilevare un lotto di errori, che è generalmente una caratteristica piuttosto buona per qualsiasi lingua. In secondo luogo, rende relativamente facile ragionare sulla lingua. Ad esempio, è relativamente facile dimostrare la correttezza formale in (sottoinsiemi di) il linguaggio Java; come confronto, ciò sarebbe praticamente impossibile in un linguaggio dinamico come Ruby et al.

Questo modo di pensare permea la lingua, ad esempio la dichiarazione forzata delle possibili eccezioni che un metodo può lanciare, il tipo separato di interface rispetto a class per evitare un'eredità multipla ambigua e così via. Per quello che è (un linguaggio realistico OOP imperativo statico con una strong attenzione alla gestione degli errori del tempo di compilazione) quelle cose sono in realtà abbastanza eleganti e potenti. Si avvicinano a linguaggi teorici (scientifici) appositamente creati per esplorare alcuni di questi problemi rispetto a qualsiasi altro linguaggio reale prima (in quel momento, intendiamoci).

. Avere un tipo void rigoroso è un messaggio chiaro: questo metodo non restituisce nulla, punto. È quello che è. Sostituirlo con l'applicazione per restituire sempre qualcosa porterebbe ad un comportamento molto più dinamico (come in Ruby dove ogni def ha un valore di ritorno esplicito o implicito, sempre), il che sarebbe negativo per provabilità e ragionamento ; o ad enorme massacro usando qualche altro meccanismo qui.

(E NB, Ruby (per esempio) lo gestisce in modo diverso, e la sua soluzione è ancora esattamente accettabile come Java, perché ha una filosofia completamente diversa, ad esempio getta completamente la provabilità e la ragionevolezza fuori dalla finestra mentre metti un focus grande sull'estrema espressività della lingua.)

    
risposta data 25.04.2017 - 16:50
fonte

Leggi altre domande sui tag