C'è qualche ragione specifica per cui hanno deciso di andare con Call by value? E 'per semplicità?
C'è qualche ragione specifica per cui hanno deciso di andare con Call by value? E 'per semplicità?
I termini "Call by Value" e "Call By Reference" sono talvolta utilizzati in modo un po 'approssimativo dai programmatori e l'uso di questi termini non sempre riflette la realtà sottostante.
Quando senti che qualcuno si riferisce a Call By Value e Call By Reference, ciò che stanno di solito dicendo è che i valori primitivi sono Call By Value, mentre gli oggetti sono Call By Reference. Puoi dire la differenza, in parte, perché quando passi un parametro per valore, ottieni sempre il valore originale. In altre parole, quando chiami per valore, la tua funzione riceve una copia della primitiva, non la primitiva effettiva. *
Chiama per riferimento è diverso. Quando chiami per riferimento, l'oggetto che stai passando può essere modificato dalla funzione, e l'oggetto manterrà tali cambiamenti quando la funzione ritorna. Java funziona così; gli oggetti passati a una funzione mantengono le modifiche apportate agli oggetti dalla funzione.
Allora perché non è Java Call by Reference, quindi?
Perché, quando si passa un oggetto all'elenco dei parametri di una funzione, non si passa effettivamente l'oggetto per riferimento. Quello che stai facendo in realtà è passare il riferimento all'oggetto, in base al valore.
So che questo può sembrare come spaccare i capelli, ma pensaci. Java crea una copia dell'oggetto prima di passarlo a te, come fa con i primitivi? No; crea una copia del riferimento e lo passa alla funzione. È possibile modificare il riferimento per puntare a un oggetto diverso e aspettarsi che tale modifica venga mantenuta quando viene restituita la funzione? No, non puoi.
* Se una variabile contenente una primitiva viene passata come parametro di funzione, viene passato il valore della variabile, non la variabile attuale. Se una espressione matematica viene passata alla funzione, l'espressione viene valutata per prima, e il risultato viene passato alla funzione in base al valore.
Java è strongmente influenzato dall'Obiettivo-C. Objective-C è strongmente influenzato da Smalltalk. Smalltalk è strongmente influenzato da Lisp. Tutti questi sono call-by-value.
Oppure, in particolare, è la condivisione di una chiamata per oggetto (ovvero chiamata per condivisione o call-by-object), che è un caso speciale di call-by-value, in cui il valore è un puntatore a un oggetto (potenzialmente mutabile).
Per le primitive, Java usa effettivamente call-by-value senza un puntatore, tuttavia, dal momento che le primitive sono immutabili, non si può comunque capire la differenza. (Puoi osservare la differenza solo quando hai due puntatori a un oggetto mutabile e le mutazioni eseguite seguendo un puntatore possono essere osservate seguendo un altro puntatore, ma le primitive non sono mutabili.)
Quindi, per rispondere alla tua domanda: storia e patrimonio.
Java ha una chiamata per valore per un numero limitato di tipi di valori predefiniti e chiama per riferimento per i tipi di oggetto. [Il riferimento è internamente a un puntatore che viene passato per valore, ma non è questo il punto.]
In C # (che è una specie di Java 3.0) ci sono i parametri out
e ref
, ma Java non li ha. Come scrittore di compilatori posso dirti che complicano davvero le cose. Devi decidere se usare un meccanismo di puntatore (simile agli oggetti) che conduce al pugilato; se usare copy-in-copy-out che porta a problemi di aliasing; come tracciare se le variabili sono inizializzate o meno. Immagino che i designer di Java pensassero che fosse troppo difficile o che non ne valesse la pena.
La vera decisione presa da Java non era quella di trattare i tipi di valore come cittadini di prima classe. Non ci sono tipi di valore definiti dall'utente, nessun boxing e passano solo per valore. In C # si pensava che valesse la pena, ma in Java pensavano che i valori primitivi e gli oggetti definiti dall'utente fossero sufficienti. Preferisco C #, ma non utilizzo quasi mai i parametri out
o ref
.
Modifica: A mia difesa, la chiamata per riferimento è stata utilizzata per descrivere una serie di strategie dagli anni '60, e il mio utilizzo qui è borderline e offenderà i puristi. Lo uso nel senso che l'oggetto non è copiato, ma qualsiasi modifica all'oggetto passato influirà sull'originale. Tuttavia, un'assegnazione al parametro passato in non influisce sull'originale, ma si riferisce invece a un nuovo oggetto (o null).
Leggi altre domande sui tag java history language-design jre