View Full Version : [JAVA] Passaggio di parametri per valore
blue_blue
06-01-2008, 23:40
Rieccomi con una nuova, entusiasmente domanda :sofico:
qualcuno mi spiega in soldoni cosa vuol dire che in java "i parametri vengono passati per valore"??
La prof non l'ha mai chiesto e sul libro c'è mezza riga, ma vorrei capirlo io per curiosità..non riesco proprio a focalizzare il concetto :fagiano:
Grazie :)
franksisca
07-01-2008, 01:40
Le variabili associate a tipi primitivi sono passate a un metodo come valore.
Cioe' viene fatta una copia e questa e' passata al metodo. Modifiche al valore passato non influenzano la variabile nel codice che richiama il metodo.
mentre con gli oggetti questo non succede, si chiama passaggio per riferimento ;)
blue_blue
09-01-2008, 09:37
Le variabili associate a tipi primitivi sono passate a un metodo come valore.
Cioe' viene fatta una copia e questa e' passata al metodo. Modifiche al valore passato non influenzano la variabile nel codice che richiama il metodo.
ah ok, qui ho capito, grazie :)
mentre con gli oggetti questo non succede, si chiama passaggio per riferimento ;)
qui invece non molto :fagiano:
e poi non mi torna con quello che c'è scritto nel mio libro (Concetti di informatica e fondamenti di Java, CAY HORTSMANN, pag 316), dove dice(non riporto tutta la pagina altrimenti ci metto una vita):
"Nei manuali Java talvolta leggete che i numeri sono passati per valore e gli oggetti sono passati per riferimento. Tecnicamente ciò non è del tutto corretto, perché in Java sia i numeri sia i riferimenti a oggetto vengono passati per valore
[qui fa un esempio e poi conclude dicendo:]
Come potete vedere, un metodo Java può aggiornare lo stato di un oggetto, ma non può sostituire il contenuto di un riferimento a oggetto. Questo dimostra che, in Java, i riferimenti a oggetto vengono passati per valore"
:wtf: :fagiano:
banryu79
09-01-2008, 09:53
Come potete vedere, un metodo Java può aggiornare lo stato di un oggetto, ma non può sostituire il contenuto di un riferimento a oggetto. Questo dimostra che, in Java, i riferimenti a oggetto vengono passati per valore"
:wtf: :fagiano:
Guarda, io ti consiglio di lasciar stare queste sottigliezze, e pensare in maniera semplicistica che le variabili primitive sono passate per valore e gli oggetti per riferimento, punto.
Tanto il nocciolo è questo.
Quello che nel tuo libro si spiega, è che in Java, sia le primitive che gli oggetti sono passati per valore, cioè con operazione di copia del loro contenuto.
Ma la differenza tra il fare una copia del contenuto di una variabile primitiva e il fare una copia del contenuto di una variabile riferimento (gli oggetti) è questa:
1)
variabile primitiva --> prendo il suo contenuto e lo copio per passarlo al metodo chiamato
es:
...
int numero = 4;
mioMetodo(numero);
...
viene passato "numero", cioè un int, come parametro al metodo "mioMetodo".
Viene passato "per valore": ma cos'è il valore di un int? il contenuto dell'int stesso, nel nostro esempio conterrà il valore 4.
2)
variabile riferimento --> prendo il suo contenuto e lo copio per passarlo al metodo chiamato
es:
...
Oggetto mioOggetto = new Oggetto();
mioAltroMetodo(mioOggetto);
...
viene passato "mioOggetto", cioè un riferimento ad un oggetto, come parametro al metodo "mioAltroMetodo".
Viene passato "per valore": ma cos'è il valore di un riferimento ad un oggetto? il contenuto del riferimento stesso, nel nostro esempio conterrà l'indirizzo in memoria in cui l'operatore "new" ha allocato l'oggetto istanziato.
Per questa ragione, tecnicamente, in Java i passaggi di parametri a metodi sono tutti "per valore"
Infatti i riferimenti, in Java, li puoi passare solo per valore: cioè puoi passare il valore di un riferimento, ovvero quello che esso contiene (un indirizzo in memoria) ma non puoi passare il riferimento "per riferimento", ovvero non puoi passare il suo stesso indirizzo (infatti anche un riferimento viene istanziato in memoria, da qualche parte, e contiene a sua volta come valore un altro indirizzo).
In altri linguaggi invece (es C++) puoi passare sia per valore che per riferimento.
Spero di non aver fatto troppo casino :stordita:
franksisca
09-01-2008, 10:31
in pratica passi il valore dell'oggetto....l'indirizzo.
prova a fare così:
public class TestingMain {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
Oggetto ogg=new Oggetto(3,4);
System.out.println(ogg);
}
}
class Oggetto{
private int x, y;
Oggetto(int x, int y){
this.x=x;
this.y=y;
}
}
...
Vero, primitivi e riferimenti sono passati per valore,
eppure non ho ancora trovato un argomento che mi convinca
che gli oggetti non sono passati per riferimento...
:eek: ;)
franksisca
09-01-2008, 11:22
Vero, primitivi e riferimenti sono passati per valore,
eppure non ho ancora trovato un argomento che mi convinca
che gli oggetti non sono passati per riferimento...
:eek: ;)
se ho capito bene, l'oggetto è passato per valore, ma il valore è un riferimento ;)
Certo se definisci oggetto = riferimento allora è passato per valore,
se invece lo consideri (come me) qualcosa a cui il riferimento punta
non vedo perché non sia passato per riferimento...
Un po' contorto, eh?
banryu79
09-01-2008, 11:46
Già, ma l'importante alla fine è capirsi :D
In Java tutto è passato per valore. Nulla è passato per riferimento. Passare per valore un oggetto vuol dire copiare l'indirizzo di memoria dell'oggetto e quindi l'oggetto di riferimento rimane invariato.
Le tue sono affermazioni assolutistiche che non spiegano/dimostrano/giustificano alcunché.
Magari supporta con qualche argomento l'affermazione "in Java tutto è passato per valore".
Certamente se per "tutto" intendi primitivi e riferimenti hai ragione...
^TiGeRShArK^
10-01-2008, 13:24
Le tue sono affermazioni assolutistiche che non spiegano/dimostrano/giustificano alcunché.
Magari supporta con qualche argomento l'affermazione "in Java tutto è passato per valore".
Certamente se per "tutto" intendi primitivi e riferimenti hai ragione...
http://forum.java.sun.com/thread.jspa?threadID=5166280&start=0&tstart=0
da leggere interamente.
Fossi matto :D
fammi un riassuntino ;)
Fossi matto :D
fammi un riassuntino ;)
Tentativo (non mi ricordo tutto il thread, però l'ho letto, eh! :sofico: ):
public class PassaggioPerValore {
private void faQualcosa() {
String[] array = new String[] {"Array", "originale"};
// C'è una casella che si chiama "array", e "punta" ad un array di stringhe.
faQualcosAltro(array);
// La casella è sempre quella, non le è successo niente.
System.out.println(array[0] + array[1]);
// Altrimenti qui avrei ricevuto un'eccezione!
}
private void faQualcosAltro(String[] array) {
// Qui arriva il valore del riferimento alla'array "array".
// Un creato una nuova casella, che "punta" allo stesso oggetto array.
array = null;
// Adesso ho svuotato la nuova casella array. Quella vecchia non ne sa nulla.
}
}
Se avessi passato il dato per riferimento, avrei passato a "faQualcosAltro" il vero riferimento all'oggetto array (cioè, ci sarebbe stata una sola casella di nome array, anche se avrei avuto l'illusione di averne due, una in faQualcosa e una in faQualcosAltro).
L'istruzione "array = null" avrebbe veramente distrutto l'oggetto originale, e il programma avrebbe dato un errore quando in seguito cercava di accedere al contenuto dell'oggetto stesso.
blue_blue
12-01-2008, 09:46
Ragazzi, vi voglio bene :cry:
Dopo le mie ultime parole famose:
La prof non l'ha mai chiesto
..indovinate A CHI l'ha domandato all'esame? :muro:
Per fortuna avevo chiesto a voi, ho fatto anche la splendida riportando le due posizioni "opposte" e dimostrando che alla fine la conclusione è la stessa :cool: :D
mi sono incartata un po' con un esempio ma vabbè, senza di voi avrei fatto una deliziosa scena muta :ciapet:
Grazie grazie mille!! :)
public class PassaggioPerValore {
private void faQualcosAltro(String[] array) {
array = null;
}
}
L'istruzione "array = null" avrebbe veramente distrutto l'oggetto originale...
(casella? :D)
Comunque questo non dipende dal fatto che array non è un vero riferimento,
ma dal fatto che l'operatore di assegnamento in java agisce sul riferimento,
in effetti l'assegnamento tra oggetti in java non esiste...
(casella? :D)
Volevo fare un disegno ma mi sono stufato. :p
Comunque questo non dipende dal fatto che array non è un vero riferimento,
ma dal fatto che l'operatore di assegnamento in java agisce sul riferimento,
in effetti l'assegnamento tra oggetti in java non esiste...
Questo non mi torna: per favore, spiegati.
Volevo dire che "array = null;" invalida il riferimento, che a quel punto non
ha piu' alcun legame con l'oggetto originale, e quindi non capisco cosa c'entri
col passaggio dell'oggetto.
fsdfdsddijsdfsdfo
16-01-2008, 02:24
veramente interessante. Letto di gusto.
Volevo dire che "array = null;" invalida il riferimento, che a quel punto non
ha piu' alcun legame con l'oggetto originale, e quindi non capisco cosa c'entri
col passaggio dell'oggetto.
beh se fosse stato un passaggio per riferimento avrebbe invalidato l'array anche fuori dalla funzione in cui c'è stato l'assegnamento. invece questo non si verifica (infatti l'array quando esce dalla funzione è tale e quale), quindi se ne deduce che il passaggio dei parametri non è mai per riferimento. ma al massimo può essere per copia del riferimento nel caso degli oggetti.
mad_hhatter
16-01-2008, 17:50
beh se fosse stato un passaggio per riferimento avrebbe invalidato l'array anche fuori dalla funzione in cui c'è stato l'assegnamento. invece questo non si verifica (infatti l'array quando esce dalla funzione è tale e quale), quindi se ne deduce che il passaggio dei parametri non è mai per riferimento. ma al massimo può essere per copia del riferimento nel caso degli oggetti.
se il parametro 'array' contiene l'indirizzo dell'oggetto, modificare il suo valore non modifica l'oggetto in sè, tanto più che null non è un oggetto, ma un valore di un riferimento e in quanto tale non può essere assegnato a un oggetto.
il passaggio per riferimento dipende, secondo me, dalla semantica degli operatori. In C ci sono operatori che operano sul contenuto di un'area di memoria sovrascrivendolo, un oggetto in Java non viene sovrascritto, è il riferimento che viene modificato per puntare a un oggetto diverso
a sto punto domando: in C, quando passo un puntatore, sto usando il passaggio per valore (del puntatore) o per riferimento?
PS: please, avvertitemi se ho scritto vaccate
PPS: ma PGI-Bis che fine ha fatto?
Rieccomi con una nuova, entusiasmente domanda :sofico:
qualcuno mi spiega in soldoni cosa vuol dire che in java "i parametri vengono passati per valore"??
La prof non l'ha mai chiesto e sul libro c'è mezza riga, ma vorrei capirlo io per curiosità..non riesco proprio a focalizzare il concetto :fagiano:
Grazie :)
mmm...forse mi è sfuggito, ma scusa ma che cosa studi? superiori o università?
è molto strano che un prof non faccia accenno a una cosa di questo tipo...almeno per quanto ho fatto io finora, all'università sono passato prima per il C poi per il java, ed è stata una delle prime cose che mi hanno insegnato...
molto strano anche che neppure ll libro ne parli
cdimauro
17-01-2008, 08:13
PPS: ma PGI-Bis che fine ha fatto?
In effetti è un pezzo che non si vede...
mad_hhatter
17-01-2008, 09:15
se il parametro 'array' contiene l'indirizzo dell'oggetto, modificare il suo valore non modifica l'oggetto in sè, tanto più che null non è un oggetto, ma un valore di un riferimento e in quanto tale non può essere assegnato a un oggetto.
il passaggio per riferimento dipende, secondo me, dalla semantica degli operatori. In C ci sono operatori che operano sul contenuto di un'area di memoria sovrascrivendolo, un oggetto in Java non viene sovrascritto, è il riferimento che viene modificato per puntare a un oggetto diverso
a sto punto domando: in C, quando passo un puntatore, sto usando il passaggio per valore (del puntatore) o per riferimento?
PS: please, avvertitemi se ho scritto vaccate
PPS: ma PGI-Bis che fine ha fatto?
in ogni caso per un linguaggio a oggetti come Java la distinzione tra passaggio di un oggetto per valore del riferimento o per riferimento mi sembra più una sottigliezza lessicale che sostanziale: di fatto non sto passando per valore l'oggetto in sè, che resta un'entità condivisa tra chiamante e funzione chiamata, configurando un passaggio per riferimento dell'entità stessa... in effetti passare per valore un riferimento è concettualmente equivalente a passare per riferimento un'area di memoria. O sbaglio?
facciamo allora un altro esperimento: se in C passo a una funzione un puntatore e la funzione modifica il valore della variabile che lo rappresenta localmente ad essa, la modifca ha effetti sull'area di memoria identificata dal puntatore? direi di no. la modifica si propaga al chiamante? il che è equivalente a chiedere: in C un puntatore viene passato per valore?
non conosco affatto bene il C, quindi aspetto risposte, non ho fatto domande retoriche :)
banryu79
17-01-2008, 09:47
se in C passo a una funzione un puntatore e la funzione modifica il valore della variabile che lo rappresenta localmente ad essa, la modifca ha effetti sull'area di memoria identificata dal puntatore?
Dipende dalla modifica... in C quando hai in mano un puntatore puoi usarlo in due modi diversi: applicandogli l'operatore di dereferenziazione (*) produci come risultato l'oggetto puntato quindi un eventuale assegnamento ha effetti sull'area di memoria identificata dal puntatore, come nell'esempio qui sotto:
[controllate se ho commesso errori... è da tempo che non scrivo più codice in C]
// dichiarazione funzione
void changeValue(int*);
---
...
---
// definizione funzione
void changeValue(int* pointer) {
*pointer = 10;
}
---
...
---
// utilizzo
int i = 6;
int *pi = i;
printf("i vale %d", i); // stampa: i vale 6
changeValue(pi);
printf("i vale %d", i); // stampa: i vale 10
L'altro modo è di utilizzare il puntatore direttamente, senza dereferenziarlo, quindi un eventuale assegnamento ha effetti sul valore stesso del puntatore, cioè il valore dell'indirizzo in memoria che conserva al suo interno.
Non so se questo risponde alla tua domanda.
// dichiarazione funzione
void changeAddress(int*);
---
...
---
// definizione funzione
void changeAddress(int* pointer) {
pointer += 4000;
}
---
...
---
// utilizzo
int i = 6;
int *pi = i;
printf("i vale %d", i); // stampa: i vale 6
printf("pi vale %p", pi); // stampa: pi vale [indirizzo memoria corrispondente a i]
changeAddress(pi);
printf("i vale %d", i); // stampa: i vale 6
printf("pi vale %p", pi); // stampa: pi vale [indirizzo memoria modificato]
@EDIT: ho scritto il post "a rate" :)
mad_hhatter
17-01-2008, 09:59
Dipende dalla modifica...
[...]
L'altro modo è di utilizzare il puntatore direttamente, senza dereferenziarlo, quindi un eventuale assegnamento ha effetti sul valore stesso del puntatore, cioè il valore dell'indirizzo in memoria che conserva al suo interno.
Non so se questo risponde alla tua domanda.
intendevo esclusivamente il secondo caso.
che succede se modifico il contenuto della variabile che contiene l'indirizzo di memoria?
in ogni caso per un linguaggio a oggetti come Java la distinzione tra passaggio di un oggetto per valore del riferimento o per riferimento mi sembra più una sottigliezza lessicale che sostanziale: di fatto non sto passando per valore l'oggetto in sè, che resta un'entità condivisa tra chiamante e funzione chiamata, configurando un passaggio per riferimento dell'entità stessa... in effetti passare per valore un riferimento è concettualmente equivalente a passare per riferimento un'area di memoria. O sbaglio?
no non è solo una sottigliezza lessicale e non sono concettualmente la stessa cosa. altrimenti un cambio di riferimento all'interno del metodo sarebbe visibile anche fuori dal metodo (un passaggio per riferimento funzionerebbe così). se uno pensa che in java avviene il passaggio per riferimento degli oggetti può commettere quindi degli errori (es. cambiare il riferimento di un oggetto dentro un metodo e credere che la modifica sia visibile fuori dal metodo).
mad_hhatter
17-01-2008, 10:40
no non è solo una sottigliezza lessicale e non sono concettualmente la stessa cosa. altrimenti un cambio di riferimento all'interno del metodo sarebbe visibile anche fuori dal metodo (un passaggio per riferimento funzionerebbe così). se uno pensa che in java avviene il passaggio per riferimento degli oggetti può commettere quindi degli errori (es. cambiare il riferimento di un oggetto dentro un metodo e credere che la modifica sia visibile fuori dal metodo).
per questo ho chiesto cosa succede se, in C, modifico il valore di un puntatore in un metodo...
e comunque il tutto dipende dalla semantica degli operatori di assegnamento
per questo ho chiesto cosa succede se, in C, modifico il valore di un puntatore in un metodo...
e comunque il tutto dipende dalla semantica degli operatori di assegnamento
no in realtà dipende dalla semantica del passaggio dei parametri. nel passaggio per riferimento non succede quello che succede in java
mad_hhatter
17-01-2008, 10:49
no in realtà dipende dalla semantica del passaggio dei parametri. nel passaggio per riferimento non succede quello che succede in java
giusto. però dipende dal fatto che in C il passaggio di un puntatore avviene esso stesso per riferimento
poi dipende dalla prospettiva: un oggetto in Java non è passato per valore, ma per riferimento... il suo riferimento è passato per valore...
blue_blue
17-01-2008, 12:00
mmm...forse mi è sfuggito, ma scusa ma che cosa studi? superiori o università?
è molto strano che un prof non faccia accenno a una cosa di questo tipo...almeno per quanto ho fatto io finora, all'università sono passato prima per il C poi per il java, ed è stata una delle prime cose che mi hanno insegnato...
molto strano anche che neppure ll libro ne parli
ho cominciato quest'anno ing biomedica..la prof non è che non l'ha fatto, ma ha liquidato l'argomento in pochi minuti, e di solito mi avevano detto che non lo chiedeva come teoria. Sul libro secondo me è spiegato in modo troppo sbrigativo..voglio dire, già qua sono venute fuori due pagine di discussione, mentre nel libro è scritto quello che ho riportato poco sopra con solo un esempio (che tra l'altro a me non ha chiarito per niente le idee)..poi boh, magari sono anche io un po' dura :fagiano: ..
... altrimenti un cambio di riferimento all'interno del metodo sarebbe visibile anche fuori dal metodo (un passaggio per riferimento funzionerebbe così)...
Non mi risulta, magari fai un esempio. :confused:
Un riferimento a un oggetto viene passato per valore, su questo non si discute, qui si discute sul passaggio dell'oggetto vero e proprio
Non mi risulta, magari fai un esempio. :confused:
Un riferimento a un oggetto viene passato per valore, su questo non si discute, qui si discute sul passaggio dell'oggetto vero e proprio
l'esempio l'ha già fatto prima un'altro utente.. basta che all'interno del metodo cambi il riferimento all'oggetto (nell'esempio si assegnava null, ma la stessa cosa succede con la creazione di una nuova istanza).
in un passaggio per riferimento la modifica sarebbe visibile anche fuori dal metodo
mad_hhatter
18-01-2008, 08:38
in un passaggio per riferimento la modifica sarebbe visibile anche fuori dal metodo
una modifica all'entità riferita, certo... una modifica del valore del riferimento, solo se esso è passato usando l'indirizzamento indiretto della variabile puntatore...
giusto?
una modifica all'entità riferita, certo... una modifica del valore del riferimento, solo se esso è passato usando l'indirizzamento indiretto della variabile puntatore...
giusto?
ammetto di non aver capito bene la domanda :stordita: :D io mi riferivo al caso di java comunque.
mad_hhatter
18-01-2008, 10:01
ammetto di non aver capito bene la domanda :stordita: :D io mi riferivo al caso di java comunque.
si, scusami, sono stato un po' criptico :)
per farla breve:
JAVA:
- tipi primitivi: passaggio per valore
- oggetti: passaggio per copia del valore del riferimento (il che equivale a passare l'oggetto in sè per riferimento)
PUNTATORI in C:
il passaggio NON avviene per copia del loro valore, ma tramite indirizzamento indiretto (altrimenti la loro modifica all'interno di un metodo non avrebbe scope globale)
C:
il passaggio di un'area di memoria tramite puntatore è un passaggio per riferimento, alla stregua del passaggio di un oggetto in java. la differenza è che in C il puntatore stesso è passato per riferimento
corretto?
si, scusami, sono stato un po' criptico :)
per farla breve:
JAVA:
- tipi primitivi: passaggio per valore
- oggetti: passaggio per copia del valore del riferimento (il che equivale a passare l'oggetto in sè per riferimento)
PUNTATORI in C:
il passaggio NON avviene per copia del loro valore, ma tramite indirizzamento indiretto (altrimenti la loro modifica all'interno di un metodo non avrebbe scope globale)
C:
il passaggio di un'area di memoria tramite puntatore è un passaggio per riferimento, alla stregua del passaggio di un oggetto in java. la differenza è che in C il puntatore stesso è passato per riferimento
corretto?
uhm no.. è molto più semplice di quello che pensi. infatti non c'è nessuna differenza di trattamento tra variabili, puntatori e oggetti (dove applicabili) in C e in Java. tutto viene passato per valore!
in java gli oggetti sono delle variabili che contengono un riferimento a un'area di memoria, quindi questo riferimento viene passato per valore. in C la cosa è equivalente con i puntatori.
per convincertene prova a eseguire questo codice:
#include <stdio.h>
#include <stdlib.h>
void foo(int* number)
{
int* anotherNumber = (int*)malloc(sizeof(int));
(*anotherNumber) = 4;
number = anotherNumber;
}
int main(int argc, char* argv[])
{
int* number = (int*)malloc(sizeof(int));
(*number) = 1;
foo(number);
printf("\n%d\n", (*number));
return EXIT_SUCCESS;
}
stesso comportamento di java
aggiungo che la credenza che il C abbia il passaggio per riferimento è fonte di innumerevoli errori
mad_hhatter
18-01-2008, 11:21
aggiungo che la credenza che il C abbia il passaggio per riferimento è fonte di innumerevoli errori
permettimi: se passi un puntatore a un metodo in C e ne modifichi il valore e tale modifica risulta globale allora il puntatore non può essere stato passato per valore, altrimenti avresti un comportamento alla java in cui modificando il riferimento a un oggetto all'interno di un metodo non modifca affatto gli altri riferimenti all'oggetto stesso
mad_hhatter
18-01-2008, 11:24
uhm no.. è molto più semplice di quello che pensi. infatti non c'è nessuna differenza di trattamento tra variabili, puntatori e oggetti (dove applicabili) in C e in Java. tutto viene passato per valore!
in java gli oggetti sono delle variabili che contengono un riferimento a un'area di memoria, quindi questo riferimento viene passato per valore. in C la cosa è equivalente con i puntatori.
per convincertene prova a eseguire questo codice:
#include <stdio.h>
#include <stdlib.h>
void foo(int* number)
{
int* anotherNumber = (int*)malloc(sizeof(int));
(*anotherNumber) = 4;
number = anotherNumber;
}
int main(int argc, char* argv[])
{
int* number = (int*)malloc(sizeof(int));
(*number) = 1;
foo(number);
printf("\n%d\n", (*number));
return EXIT_SUCCESS;
}
stesso comportamento di java
in java un oggetto non è passato per valore, ma per riferimento, o, più precisamente, per copia del valore di un riferimento che punta ad esso. Ma l'oggetto passatto non viene copiato
non confondere l'oggetto con il suo riferimento!
in java un oggetto non è passato per valore, ma per riferimento, o, più precisamente, per copia del valore di un riferimento che punta ad esso. Ma l'oggetto passatto non viene copiato
non confondere l'oggetto con il suo riferimento!
intendo dire che in java un'oggetto è una variabile che contiene il riferimento a un'area di memoria. questa variabile è passata per valore come tutte le altre variabili, non c'è un trattamento speciale per gli oggetti.
mad_hhatter
18-01-2008, 11:42
intendo dire che in java un'oggetto è una variabile che contiene il riferimento a un'area di memoria. questa variabile è passata per valore come tutte le altre variabili, non c'è un trattamento speciale per gli oggetti.
il tuo errore è la confuzione dei termini reference e object.
quello che tu chiami variabile identifica il reference, non l'object
il reference è passato per valore e tale fatto implica che l'object identificato dal reference è passato per riferimento
mad_hhatter
18-01-2008, 11:44
#include <stdio.h>
#include <stdlib.h>
void foo(int* number)
{
int* anotherNumber = (int*)malloc(sizeof(int));
(*anotherNumber) = 4;
number = anotherNumber;
}
int main(int argc, char* argv[])
{
int* number = (int*)malloc(sizeof(int));
(*number) = 1;
foo(number);
printf("\n%d\n", (*number));
return EXIT_SUCCESS;
}
stesso comportamento di java
prova in java a fare lo stesso per favore :)
il tuo errore è la confuzione dei termini reference e object.
quello che tu chiami variabile identifica il reference, non l'object
il reference è passato per valore e tale fatto implica che l'object identificato dal reference è passato per riferimento
no non c'è nessun passaggio per riferimento, altrimenti l'esempio sotto darebbe come risultato 4.
un oggetto è una variabile che contiene un reference, ma non per questo possiamo dire che esiste il passaggio per riferimento in java. è proprio lo stesso discorso del C, ne più ne meno
prova in java a fare lo stesso per favore :)
certamente:
public class Prova {
public static void main(String[] args) {
Integer number = new Integer(1);
foo(number);
System.out.println(number.toString());
}
public static void foo(Integer number) {
Integer anotherNumber = new Integer(4);
number = anotherNumber;
}
}
il risultato è identico alla versione C
mad_hhatter
18-01-2008, 12:00
no non c'è nessun passaggio per riferimento, altrimenti l'esempio sotto darebbe come risultato 4.
un oggetto è una variabile che contiene un reference, ma non per questo possiamo dire che esiste il passaggio per riferimento in java. è proprio lo stesso discorso del C, ne più ne meno
certamente:
public class Prova {
public static void main(String[] args) {
Integer number = new Integer(1);
foo(number);
System.out.println(number.toString());
}
public static void foo(Integer number) {
Integer anotherNumber = new Integer(4);
number = anotherNumber;
}
}
il risultato è identico alla versione C
spiacente, ma non hai dimostrato nulla: semplicemente number è la copia del riferimento all'oggetto integer. modificando il valore di number semplicemente lo associ a un nuovo oggetto.
guarda:
public class Test1 {
public static void main(String[] args) {
int i = 0;
foo(i);
System.out.println(i);
Integer j = 0;
foo(j);
System.out.println(j);
Bla b = new Bla();
foo(b);
System.out.println(b.value);
}
private static void foo(int i) {
i = 4;
}
private static void foo(Integer i) {
i = 4;
}
private static void foo(Bla b){
b.value = 4;
}
static class Bla {
int value;
}
}
b è passato per riferimento, infatti lo modifico
mad_hhatter
18-01-2008, 12:01
#include <stdio.h>
#include <stdlib.h>
void foo(int* number)
{
int* anotherNumber = (int*)malloc(sizeof(int));
(*anotherNumber) = 4;
number = anotherNumber;
}
int main(int argc, char* argv[])
{
int* number = (int*)malloc(sizeof(int));
(*number) = 1;
foo(number);
printf("\n%d\n", (*number));
return EXIT_SUCCESS;
}
scusa, mi potresti dire qual è il risultato di questo? non mi ricordo nulla di C
^TiGeRShArK^
18-01-2008, 12:04
il tuo errore è la confuzione dei termini reference e object.
quello che tu chiami variabile identifica il reference, non l'object
il reference è passato per valore e tale fatto implica che l'object identificato dal reference è passato per riferimento
..mi sa che l'errore è il tuo dato che konte ha perfettamente ragione.
Come spiega in maniera molto approfondita il link che avevo postato, in java esiste solo ed esclusivamente il passaggio per valore.
Infatti in java esistono essenzialmente i primitive type e i reference type.
I primitive type sono tutti i tipi primitivi, mentre i reference type comprendono i vari oggetti e arrays.
Quando tu passi un parametro ad un metodo esso non fa altro che ricevere per copia il contenuto della variabile che gli stai passando.
Poichè i primitive type contengono al loro interno semplicemente un valore, all'interno della funzione vedrai direttamente questo valore.
Poichè i reference type contengono al loro interno un riferimento (come dice il nome stesso d'altronde), allora in quel caso viene passato per copia il valore del reference type, che non è altro che il riferimento dell'oggetto.
Ovviamente tale passaggio NON è assolutamente un passaggio per riferimento dato che non puoi in alcun modo modificare il riferimento iniziale, ma puoi semplicemente agire sulla copia di tale riferimento.
Tanto per concludere, è inutile continuare a dibattere dato che Gosling stesso aveva ben chiarito questo concetto nelle specifiche del linguaggio Java, come evidenziato lungo il corso del thread che ho linkato.
Se volete continuare a credere che in java esista il passaggio per riferimento, allora fate pure.
Però state sbagliando dato che non è una questione di opinioni personali, ma di definizioni che sono state date in un certo modo all'atto della creazione del linguaggio Java e contenute nelle sue specifiche.
mad_hhatter
18-01-2008, 12:08
..mi sa che l'errore è il tuo dato che konte ha perfettamente ragione.
Come spiega in maniera molto approfondita il link che avevo postato, in java esiste solo ed esclusivamente il passaggio per valore.
Infatti in java esistono essenzialmente i primitive type e i reference type.
I primitive type sono tutti i tipi primitivi, mentre i reference type comprendono i vari oggetti e arrays.
Quando tu passi un parametro ad un metodo esso non fa altro che ricevere per copia il contenuto della variabile che gli stai passando.
Poichè i primitive type contengono al loro interno semplicemente un valore, all'interno della funzione vedrai direttamente questo valore.
Poichè i reference type contengono al loro interno un riferimento (come dice il nome stesso d'altronde), allora in quel caso viene passato per copia il valore del reference type, che non è altro che il riferimento dell'oggetto.
Ovviamente tale passaggio NON è assolutamente un passaggio per riferimento dato che non puoi in alcun modo modificare il riferimento iniziale, ma puoi semplicemente agire sulla copia di tale riferimento.
Tanto per concludere, è inutile continuare a dibattere dato che Gosling stesso aveva ben chiarito questo concetto nelle specifiche del linguaggio Java, come evidenziato lungo il corso del thread che ho linkato.
Se volete continuare a credere che in java esista il passaggio per riferimento, allora fate pure.
Però state sbagliando dato che non è una questione di opinioni personali, ma di definizioni che sono state date in un certo modo all'atto della creazione del linguaggio Java e contenute nelle sue specifiche.
io ho affermato che il passaggio di un oggetto (concettualmente, visto che il passaggio coinvolge il reference, non l'oggetto) è per riferimento e non per copia... non mi pare di aver detto vaccate
per dirla in altro modo, sullo stack non viene posta una copia dell'oggetto, ma una copia del reference che punta a d esso.
è giusto o sbaglio?
spiacente, ma non hai dimostrato nulla: semplicemente number è la copia del riferimento all'oggetto integer. modificando il valore di number semplicemente lo associ a un nuovo oggetto.
guarda:
public class Test1 {
public static void main(String[] args) {
int i = 0;
foo(i);
System.out.println(i);
Integer j = 0;
foo(j);
System.out.println(j);
Bla b = new Bla();
foo(b);
System.out.println(b.value);
}
private static void foo(int i) {
i = 4;
}
private static void foo(Integer i) {
i = 4;
}
private static void foo(Bla b){
b.value = 4;
}
static class Bla {
int value;
}
}
b è passato per riferimento, infatti lo modifico
il fatto che lo puoi modificare non significa che ci sia stato un passaggio per riferimento. so bene che la differenza è sottile, ma una cosa è vera finchè non si dimostra il contrario e nella fattispecie il tuo esempio sembrerebbe assecondare l'ipotesi che in java c'è il passaggio per riferimento.. se non fosse che l'esempio che ho fatto prima dimostra il contrario.
ecco per essere più chiari faccio un esempio di passaggio per riferimento in C++
#include <stdio.h>
#include <stdlib.h>
void foo(int &number)
{
int anotherNumber = 4;
number = anotherNumber;
}
int main(int argc, char* argv[])
{
int number = 1;
foo(number);
printf("\n%d\n", number);
return EXIT_SUCCESS;
}
scusate se lo stile è C-like ma ho adattato l'esempio scritto in C.
ora guardando in giro per internet, pare che il tipo di passaggio dei parametri usato da java per gli oggetti e da C per i puntatori si chiami per indirizzo. ma in realtà non è altro che un passaggio per valore (con il valore che è un indirizzo)
^TiGeRShArK^
18-01-2008, 12:17
io ho affermato che il passaggio di un oggetto (concettualmente, visto che il passaggio coinvolge il reference, non l'oggetto) è per riferimento e non per copia... non mi pare di aver detto vaccate
per dirla in altro modo, sullo stack non viene posta una copia dell'oggetto, ma una copia del reference che punta a d esso.
è giusto o sbaglio?
Sbagli.
Does Java pass objects by reference or by value?
The answer is NO! The fact is that Java has no facility whatsoever to pass an object to any function! The reason is that Java has no variables that contain objects.
per approfondire, visto che mi pare che avete confusione proprio nelle definizioni di base ecco due link che dovrebbero spiegare il concetto meglio di quanto riuscirei a fare io:
http://www.javaworld.com/javaworld/javaqa/2000-05/03-qa-0526-pass.html
http://www.yoda.arachsys.com/java/passing.html
scusa, mi potresti dire qual è il risultato di questo? non mi ricordo nulla di C
il risultato è: 1
lo stesso risultato si ottiene anche per l'esempio che ho postato in java, mentre l'esempio che ho appena postato in C++ restituisce 4
mad_hhatter
18-01-2008, 12:23
Sbagli.
per approfondire, visto che mi pare che avete confusione proprio nelle definizioni di base ecco due link che dovrebbero spiegare il concetto meglio di quanto riuscirei a fare io:
http://www.javaworld.com/javaworld/javaqa/2000-05/03-qa-0526-pass.html
http://www.yoda.arachsys.com/java/passing.html
perdonami, ma cosa, della frase "io ho affermato che il passaggio di un oggetto (concettualmente, visto che il passaggio coinvolge il reference, non l'oggetto) è per riferimento e non per copia..." fa intendere che venga passato l'oggetto e non il reference?
ho usato la parola "concettualmente" apposta...
e cmq non vedo perché ti debba scaldare
Sbagli.
per approfondire, visto che mi pare che avete confusione proprio nelle definizioni di base ecco due link che dovrebbero spiegare il concetto meglio di quanto riuscirei a fare io:
http://www.javaworld.com/javaworld/javaqa/2000-05/03-qa-0526-pass.html
http://www.yoda.arachsys.com/java/passing.html
Mmmm... bene, quindi mi sembra di aver capito bene (e il mio esempio era corretto, perciò).
Una curiosità (sì, lo so, basterebbe leggersi le specifiche del C++ ma... forse voi mi potete dare la risposta più velocemente): nemmeno in C++ credo che esista la variabile in grado di contenere un'oggetto... semplicemente, immagino che il passaggio per riferimento sia implementato come un passaggio doppiamente inderetto, cioè, mentre in Java ciò che viene passato è il riferimento ad un oggetto copiandone il valore nello stack della funzione chiamata (e ogni operazione su di esso, meno l'assegnamento, viene fatta dereferenziandolo, cioè in Java non esiste un'aritmetica dei puntatori), in C++ è possibile passare il riferimento al riferimento, cioè un puntatore all'area di memoria contenente il puntatore all'oggetto... in sostanza, l'indirizzo di (&) una variabile che è già un puntatore.
Ho indovinato? :stordita:
Dovrei scrivere un romanzo, ma vedo che mad_hhatter ha già scritto tutto
quello che avevo in mente, e si è pure beccato vari insulti al mio posto, quindi grazie :D
Visto che parlate di specifiche, gosling e sua nonna in carriola,
magari postate dei link risolutivi, non i soliti swap non funzionanti,
che dimostrano solo che i riferimenti sono passati per valore
(grazie, già lo sapevo!)
Come detto molto prima, se per voi oggetto = riferimento allora avete ragione,
per me l'oggetto è quello a cui il riferimento punta.
Oppure diciamo che in java gli oggetti non esistono, è una posizione accettabile,
ma allora tutto il modello di astrazione di java non ha più senso.
A presto.
Dovrei scrivere un romanzo, ma vedo che mad_hhatter ha già scritto tutto
quello che avevo in mente, e si è pure beccato vari insulti al mio posto, quindi grazie :D
Visto che parlate di specifiche, gosling e sua nonna in carriola,
magari postate dei link risolutivi, non i soliti swap non funzionanti,
che dimostrano solo che i riferimenti sono passati per valore
(grazie, già lo sapevo!)
Come detto molto prima, se per voi oggetto = riferimento allora avete ragione,
per me l'oggetto è quello a cui il riferimento punta.
Oppure diciamo che in java gli oggetti non esistono, è una posizione accettabile,
ma allora tutto il modello di astrazione di java non ha più senso.
A presto.
pensavo che l'esempio in C++ di passaggio di parametri per riferimento avesse chiarito ogni dubbio.. spero che noti una differenza sostanziale rispetto all'esempio java e se è così è evidente che non è possibile chiamarli con lo stesso nome
ps. ti potrà sembrare una sottigliezza, ma non comprendere a fondo il meccanismo di passaggio dei parametri è fonte di innumerevoli errori
pps. se sapevi che i riferimenti sono passati per valore allora sapevi anche che gli oggetti non sono passati per riferimento
^TiGeRShArK^
19-01-2008, 19:40
Dovrei scrivere un romanzo, ma vedo che mad_hhatter ha già scritto tutto
quello che avevo in mente, e si è pure beccato vari insulti al mio posto, quindi grazie :D
Visto che parlate di specifiche, gosling e sua nonna in carriola,
magari postate dei link risolutivi, non i soliti swap non funzionanti,
che dimostrano solo che i riferimenti sono passati per valore
(grazie, già lo sapevo!)
Come detto molto prima, se per voi oggetto = riferimento allora avete ragione,
per me l'oggetto è quello a cui il riferimento punta.
Oppure diciamo che in java gli oggetti non esistono, è una posizione accettabile,
ma allora tutto il modello di astrazione di java non ha più senso.
A presto.
guarda..
per me puoi tenerti tutte le convinzioni che vuoi..
Ma come ho scritto prima in java esistono solo due tipi:
i primitive type e i reference type.
Ovviamente gli oggetti appartengono ai reference type dato che come ho riportato e come è spiegato molto chiaramente nei link che ho riportato in java non esiste alcuna variabile che contiene un oggetto.
mad_hhatter
19-01-2008, 20:24
guarda..
per me puoi tenerti tutte le convinzioni che vuoi..
Ma come ho scritto prima in java esistono solo due tipi:
i primitive type e i reference type.
Ovviamente gli oggetti appartengono ai reference type dato che come ho riportato e come è spiegato molto chiaramente nei link che ho riportato in java non esiste alcuna variabile che contiene un oggetto.
allora, vediamo di riassumere quello che hai detto:
1) "oggetto" E' un reference type
2) "variabile" non contiene un oggetto
implica: "variabile" non contiene un sottoinsieme di tutti i reference type
domanda: come si usano i reference type che rappresentano oggetti se non sono nominabili tramite variabile?
ovviamente da qualche parte il tuo discorso non quadra.
Ora RIespongo il mio pensiero cercando di essere piu' formale e preciso di quanto sia stato in precedenza (visto che, rileggendomi, ho notato parecchie imprecisioni).
Un reference type e' una variabile che contiene un riferimento, un link, un puntatore a un'entita' residente nello heap e che costituisce un oggetto, cioe' un'istanza di una classe. ATTENZIONE: "oggetto" e' diverso da "reference"!
Ora, i parametri di un metodo possono essere reference type o primitive type, concentramoci sui reference type... concordiamo tutti sul fatto che un parametro in java e' passato solo per valore.
MA, poiche' un reference type ha senso solo in quanto rappresentante dell'oggetto a cui esso fa riferimento, e' comune identificare (SOLO A LIVELLO CONCETTUALE, per semplicita' di ragionamento) il reference con l'oggetto.
In questo senso diciamo (consci di commettere un abuso di notazione, e sempre parlando a livello di rappresentazione concettuale e a puro scopo semplificativo) che il fatto di passare per valore un reference EQUIVALE (nel senso che "e' come se... anche se tecnicamente non succede per davvero") a passare per riferimento l'oggetto a cui punta il reference passato.
Ora, siccome il secondo dei link che hai postato per ultimi dice a un certo punto che in C (dove abbiamo appuranto che esiste solo il passaggio per valore) e' possibile simulare il passaggio per riferimento usando i puntatori (ma di fatto sto passando per valore il puntatore di qualcosa), non vedo perche' io debba essere accusato di dire stronzate quando dico che in java passare per valore il riferimento a un oggetto equivale concettualmente a passare l'oggetto per riferimento (sto persino usando gli stessi termini :D ).
Piu' terra terra: un oggetto e' passato per riferimento perche' l'unica cosa che mi permette di operare su e con un oggetto e' il suo riferimento.
Se non e' chiaro, la parola importante del mio discorso e' quel "concettualmente".
In questo senso diciamo (consci di commettere un abuso di notazione, e sempre parlando a livello di rappresentazione concettuale e a puro scopo semplificativo) che il fatto di passare per valore un reference EQUIVALE (nel senso che "e' come se... anche se tecnicamente non succede per davvero") a passare per riferimento l'oggetto a cui punta il reference passato.
il problema è proprio qui! passare per valore il riferimento non equivale affatto a passare per riferimento l'oggetto, altrimenti come chiameresti il passaggio di parametri dell'esempio che ho postato in C++?
mad_hhatter
19-01-2008, 20:42
pensavo che l'esempio in C++ di passaggio di parametri per riferimento avesse chiarito ogni dubbio.. spero che noti una differenza sostanziale rispetto all'esempio java e se è così è evidente che non è possibile chiamarli con lo stesso nome
ps. ti potrà sembrare una sottigliezza, ma non comprendere a fondo il meccanismo di passaggio dei parametri è fonte di innumerevoli errori
pps. se sapevi che i riferimenti sono passati per valore allora sapevi anche che gli oggetti non sono passati per riferimento
nell'esempio in C++ le cose vanno diversamente perche' la semantica dell'operatore di assegnamento e' diversa da java.
Nella versione java stai dicendo:
"prendi il rimerimento number e fallo puntare a questo nuovo oggetto". ovviamente number e' una copia e il riferimento originario (quello del chiamante) non viene toccato.
In C++:
ti fai dare l'indirizzo di un'entita' e poi dici: all'entita' presente a quell'indirizzo fai assumere questo valore
il che mi sembra assomigliare molto a quello che, in java, si fa partendo dal riferimento a un oggetto che contiene un dato membro e si cambia il valore di quest'ultimo.
nota che ho detto assomigliare, non "essere esattamente la stessa cosa"
mad_hhatter
19-01-2008, 20:50
il problema è proprio qui! passare per valore il riferimento non equivale affatto a passare per riferimento l'oggetto, altrimenti come chiameresti il passaggio di parametri dell'esempio che ho postato in C++?
e tu come lo chiami, in java, il "passaggio di un oggetto" (lo so, non viene passato l'oggetto, ma passami l'abuso di linguaggio)? lo chiami "per valore"?
certo, in C++ sovrascrivi l'oggetto (o almeno questo e' quello che deduco dal tuo esempio), in java non puoi, ok. pero' in java, limitatamente agli oggetti, posso modificarne i membri emulando una sovrascrittura.
di sicuro in java un oggetto non e' passato per valore, quindi io lo chiamo, per semplicita', passaggio per riferimento. sempre concettualemte e consapevole dell'imprecisione.
nell'esempio in C++ le cose vanno diversamente perche' la semantica dell'operatore di assegnamento e' diversa da java.
Nella versione java stai dicendo:
"prendi il rimerimento number e fallo puntare a questo nuovo oggetto". ovviamente number e' una copia e il riferimento originario (quello del chiamante) non viene toccato.
In C++:
ti fai dare l'indirizzo di un'entita' e poi dici: all'entita' presente a quell'indirizzo fai assumere questo valore
il che mi sembra assomigliare molto a quello che, in java, si fa partendo dal riferimento a un oggetto che contiene un dato membro e si cambia il valore di quest'ultimo.
nota che ho detto assomigliare, non "essere esattamente la stessa cosa"
no perchè in C++ puoi usare variabili normali, puntatori o oggetti, quello che vuoi, ma ottieni sempre lo stesso risultato. non farti ingannare dal fatto che ho usato un int e non un oggetto
ps. devo scappare :fagiano: se non mi sono spiegato bene mi spiegherò meglio un'altra volta :P
mad_hhatter
19-01-2008, 20:54
no perchè in C++ puoi usare variabili normali, puntatori o oggetti, quello che vuoi, ma ottieni sempre lo stesso risultato. non farti ingannare dal fatto che ho usato un int e non un oggetto
ps. devo scappare :fagiano: se non mi sono spiegato bene mi spiegherò meglio un'altra volta :P
vorrei chiederti se, nel tuo esempio C++, number = anotherNumber sovrascrive l'area di memoria puntata da &number o se viene modificato il valore del puntatore per puntatre al nuovo oggetto.
e comunque, e' chiaro che java e c++ sono molto diversi, ma io sto parlando appunto di soli oggetti e in maniera del tutto concettuale.
mad_hhatter
19-01-2008, 21:00
quando, in C++, faccio un passaggio di un parametro per riferimento, nello stack cosa viene memorizzato? l'indirizzo del parametro? o l'indirizzo a cui si trova un puntatore ad esso?
in java, per quanto posso immaginare, nello stack finisce una copia dell'indirizzo dell'oggetto, cioe', appunto, una copia del valore del suo reference
kingmastermind
19-01-2008, 21:02
Scusate se mi intrometto nel forum, ma visto che ho la fortuna di potere chiedere a degli esperti di [Java], volevo sapere secondo la vostra esperienza se in termini di calcolo Moltiplicazioni, divisioni, somme ecc. questo linguaggio, a me sconosciuto, possa essere paragonabile o superiore al [C++] o al [C#]! Vi chiedo questo perchè sono sinceramente interessato al linguaggio ma ho sempre creduto che fosse inferiore in termini di calcolo puro rispetto al [C]! Grazie comunque!:)
mad_hhatter
19-01-2008, 21:06
Scusate se mi intrometto nel forum, ma visto che ho la fortuna di potere chiedere a degli esperti di [Java], volevo sapere secondo la vostra esperienza se in termini di calcolo Moltiplicazioni, divisioni, somme ecc. questo linguaggio, a me sconosciuto, possa essere paragonabile o superiore al [C++] o al [C#]! Vi chiedo questo perchè sono sinceramente interessato al linguaggio ma ho sempre creduto che fosse inferiore in termini di calcolo puro rispetto al [C]! Grazie comunque!:)
a parte il fatto che grazie al compilatore JIT java non e' piu' dichiarabile "sempre piu' lento rispetto al C/C++", credo che per quanto riguarda la pura esecuzione di una operazione aritmetica, usando appunto il JIT, non ci sia alcuna differenza di prestazioni
kingmastermind
19-01-2008, 21:08
Esistono compilatori free e se si quali conviene scaricare! Mi pare di avere sentito parlare di Eclipse o sbaglio? Grazie!
mad_hhatter
19-01-2008, 21:13
Esistono compilatori free e se si quali conviene scaricare! Mi pare di avere sentito parlare di Eclipse o sbaglio? Grazie!
per java e' sempre esistito in forma assolutamente gratuita il sdk (detto jdk) con tutto il necessario. se vuoi anche un ide eclipse e' uno dei piu' importanti assieme a netbeans
se vuoi qualcosa di piu' semplice puoi usare jcreator
mad_hhatter
19-01-2008, 21:14
sigh :(
?
^TiGeRShArK^
19-01-2008, 21:17
Scusate se mi intrometto nel forum, ma visto che ho la fortuna di potere chiedere a degli esperti di [Java], volevo sapere secondo la vostra esperienza se in termini di calcolo Moltiplicazioni, divisioni, somme ecc. questo linguaggio, a me sconosciuto, possa essere paragonabile o superiore al [C++] o al [C#]! Vi chiedo questo perchè sono sinceramente interessato al linguaggio ma ho sempre creduto che fosse inferiore in termini di calcolo puro rispetto al [C]! Grazie comunque!:)
le operazioni in floating point pure se non erro sono + lente dato che vengono fatte in emulazione e non in maniera nativa perchè hanno requisiti + stringenti rispetto a quanto utilizzato per il C++.
O almeno era così fino ad un pò di tempo fa, ora sinceramente dovrei informarmi se la situazione è cambiata oppure no.
Per quanto riguarda il tema del topic ora non posso rsp che sto scappando...
se non torno troppo ubriaco rispondo stanotte :O
:asd:
mad_hhatter
19-01-2008, 21:18
tornando IT:
citando dal link di ^TiGeRShArK^: http://www.yoda.arachsys.com/java/passing.html
"reference
The L-value of the formal parameter is set to the L-value of the actual parameter. In other words, the address of the formal parameter is the same as the address of the actual parameter. Any modifications to the formal parameter also immediately affect the actual parameter."
ora, se, concettualmente, pensiamo di passare a un metodo un oggetto (e risottolineao il concettualmente), mi pare che il comportamente in java sia esattamente quello descritto.
kingmastermind
19-01-2008, 21:19
Sono andato velocemente a vedere nei siti in italiano! Cosa vuol dire Abilitare JIT e disabilitarlo? Si tratta forse di una ottimizzazione come in [C++] -O3 -O2 ecc. ?
mad_hhatter
19-01-2008, 21:30
Sono andato velocemente a vedere nei siti in italiano! Cosa vuol dire Abilitare JIT e disabilitarlo? Si tratta forse di una ottimizzazione come in [C++] -O3 -O2 ecc. ?
http://en.wikipedia.org/wiki/Just-in-time_compilation
kingmastermind
19-01-2008, 21:32
Grazie infinite ! Buona notte! Domani ci smanetto un poco!:cool:
Esistono compilatori free e se si quali conviene scaricare! Mi pare di avere sentito parlare di Eclipse o sbaglio? Grazie!
25 anni giusto? :(
e tu come lo chiami, in java, il "passaggio di un oggetto" (lo so, non viene passato l'oggetto, ma passami l'abuso di linguaggio)? lo chiami "per valore"?
certo, in C++ sovrascrivi l'oggetto (o almeno questo e' quello che deduco dal tuo esempio), in java non puoi, ok. pero' in java, limitatamente agli oggetti, posso modificarne i membri emulando una sovrascrittura.
di sicuro in java un oggetto non e' passato per valore, quindi io lo chiamo, per semplicita', passaggio per riferimento. sempre concettualemte e consapevole dell'imprecisione.
potresti chiamarlo passaggio per indirizzo come fa qualcuno.. l'unica cosa certa è che non è passaggio per riferimento.
perchè:
tornando IT:
citando dal link di ^TiGeRShArK^: http://www.yoda.arachsys.com/java/passing.html
"reference
The L-value of the formal parameter is set to the L-value of the actual parameter. In other words, the address of the formal parameter is the same as the address of the actual parameter. Any modifications to the formal parameter also immediately affect the actual parameter."
ora, se, concettualmente, pensiamo di passare a un metodo un oggetto (e risottolineao il concettualmente), mi pare che il comportamente in java sia esattamente quello descritto.
nel caso di java l'L-value del parametro formale e l'L-value del parametro reale sono diversi SEMPRE. tieni conto che i parametri sono variabili e le variabili non contengono MAI oggetti, ma al massimo riferimenti ad essi. se tu vuoi continuare a parlare di oggetti in maniera astratta sappi che non arriviamo da nessuna parte.. java non funziona in maniera astratta :fagiano:
vorrei chiederti se, nel tuo esempio C++, number = anotherNumber sovrascrive l'area di memoria puntata da &number o se viene modificato il valore del puntatore per puntatre al nuovo oggetto.
e comunque, e' chiaro che java e c++ sono molto diversi, ma io sto parlando appunto di soli oggetti e in maniera del tutto concettuale.
#include <stdio.h>
#include <stdlib.h>
class Integer {
private:
int m_number;
public:
inline Integer() {m_number = 0;}
inline Integer(int number) {m_number = number;}
inline int toInt() {return m_number;}
};
void foo(Integer* &number)
{
Integer* anotherNumber = new Integer(4);
number = anotherNumber;
}
int main(int argc, char* argv[])
{
Integer* number = new Integer(1);
foo(number);
printf("\n%d\n", number->toInt());
return EXIT_SUCCESS;
}
succede che il risultato è comunque 4 :read: questo è passaggio per riferimento, cioè il parametro è la variabile che viene passata per parametro, non una cosa simile
mad_hhatter
20-01-2008, 01:43
potresti chiamarlo passaggio per indirizzo come fa qualcuno.. l'unica cosa certa è che non è passaggio per riferimento.
perchè:
nel caso di java l'L-value del parametro formale e l'L-value del parametro reale sono diversi SEMPRE. tieni conto che i parametri sono variabili e le variabili non contengono MAI oggetti, ma al massimo riferimenti ad essi. se tu vuoi continuare a parlare di oggetti in maniera astratta sappi che non arriviamo da nessuna parte.. java non funziona in maniera astratta :fagiano:
indirizzo, riferimento... mi spieghi la differenza?
perdonami, ma cos'e' un reference se non un L-value di un particolare oggetto?
possibile che non sia ancora chiaro che non sto parlando di come funziona java, ma sto solo rappresentando il passaggio di parametri (nel solo caso in cui essi siano reference type) "immaginando che" il parametro passato sia l'oggetto e non il suo riferimento (chissa' perche' parliamo di riferimento di un oggetto e io non posso usare il termine passaggio per riferimento visto che, anche tecnicamente, cio' che viene passato e' proprio il riferimento all'oggetto, sia pure soltanto per copia...). E' un modo colloquiale di parlare, se vuoi, o di ragionare in termini spiccioli... ancora, e' un modo per identificare il fatto che l'oggetto non e' passato per copia e, visto che di fatto in java non esiste il passaggio per riferimento, parlando di passaggio per riferimento non introduco ambiguita' o possibilita' di fraintendimenti.
mad_hhatter
20-01-2008, 01:50
#include <stdio.h>
#include <stdlib.h>
class Integer {
private:
int m_number;
public:
inline Integer() {m_number = 0;}
inline Integer(int number) {m_number = number;}
inline int toInt() {return m_number;}
};
void foo(Integer* &number)
{
Integer* anotherNumber = new Integer(4);
number = anotherNumber;
}
int main(int argc, char* argv[])
{
Integer* number = new Integer(1);
foo(number);
printf("\n%d\n", number->toInt());
return EXIT_SUCCESS;
}
succede che il risultato è comunque 4 :read: questo è passaggio per riferimento, cioè il parametro è la variabile che viene passata per parametro, non una cosa simile
tu continui a farmi esempi reali... ho capito che in java il passaggio per riferimento non esiste, mentre in c++ si. non e' questo il punto!
io parlo soltanto a livello di astrazione mentale, nulla di cio' che descrivo avviene realmente, e' solo un modo di immaginare, di SEMPLIFICARE, quello che avviene.
possibile che non mi sia ancora spiegato su questo punto?
indirizzo, riferimento... mi spieghi la differenza?
perdonami, ma cos'e' un reference se non un L-value di un particolare oggetto?
no il pezzo che hai quotato prima dal link parla di L-value di una variabile (il parametro), non di un oggetto.
l'L-value è l'indirizzo di memoria della variabile, mentre il reference è il contenuto di una variabile di tipo reference che a sua volta può essere interpretato come L-value di un oggetto. ma considerando che in java le variabili non contengono MAI oggetti allora si può dedurre che il reference non sarà MAI l'L-value di nessuna variabile, ne tantomeno di un parametro. motivo per cui quello che hai quotato dal link è esatto e non porta alle conclusioni a cui sei arrivato.
possibile che non sia ancora chiaro che non sto parlando di come funziona java, ma sto solo rappresentando il passaggio di parametri (nel solo caso in cui essi siano reference type) "immaginando che" il parametro passato sia l'oggetto e non il suo riferimento (chissa' perche' parliamo di riferimento di un oggetto e io non posso usare il termine passaggio per riferimento visto che, anche tecnicamente, cio' che viene passato e' proprio il riferimento all'oggetto, sia pure soltanto per copia...). E' un modo colloquiale di parlare, se vuoi, o di ragionare in termini spiccioli... ancora, e' un modo per identificare il fatto che l'oggetto non e' passato per copia e, visto che di fatto in java non esiste il passaggio per riferimento, parlando di passaggio per riferimento non introduco ambiguita' o possibilita' di fraintendimenti.
già il fatto che immagini di passare l'oggetto è sbagliato in sè, ma anche ammettendo di poterlo immaginare crei fraintendimenti perchè il concetto di passaggio per riferimento è un concetto generale che non si applica solo a java, ma ai linguaggi in generale (la definizione mica l'ho inventata io). se tu mi dici che in java gli oggetti vengono passati per riferimento allora io potrei scrivere una cosa come quella che ho appena scritto in C++ e pretendere che funzioni, invece non funziona.
tu continui a farmi esempi reali... ho capito che in java il passaggio per riferimento non esiste, mentre in c++ si. non e' questo il punto!
no? :fagiano:
io parlo soltanto a livello di astrazione mentale, nulla di cio' che descrivo avviene realmente, e' solo un modo di immaginare, di SEMPLIFICARE, quello che avviene.
possibile che non mi sia ancora spiegato su questo punto?
ma qui non si tratta di semplificare.. al contrario si sta complicando una questione ultrasemplice.
voi dite:
in java i tipi primitivi sono passati per valore mentre gli oggetti sono passati per riferimento (beh ad eccezione degli oggetti immutabili ecc..)
mentre in realtà:
in java tutto viene passato per valore
quale ti sembra più semplice? :fagiano:
mad_hhatter
20-01-2008, 02:06
no il pezzo che hai quotato prima dal link parla di L-value di una variabile (il parametro), non di un oggetto.
l'L-value è l'indirizzo di memoria della variabile, mentre il reference è il contenuto di una variabile di tipo reference che a sua volta può essere interpretato come L-value di un oggetto. ma considerando che in java le variabili non contengono MAI oggetti allora si può dedurre che il reference non sarà MAI l'L-value di nessuna variabile, ne tantomeno di un parametro. motivo per cui quello che hai quotato dal link è esatto e non porta alle conclusioni a cui sei arrivato.
già il fatto che immagini di passare l'oggetto è sbagliato in sè, ma anche ammettendo di poterlo immaginare crei fraintendimenti perchè il concetto di passaggio per riferimento è un concetto generale che non si applica solo a java, ma ai linguaggi in generale (la definizione mica l'ho inventata io). se tu mi dici che in java gli oggetti vengono passati per riferimento allora io potrei scrivere una cosa come quella che ho appena scritto in C++ e pretendere che funzioni, invece non funziona.
e invece no, perche' se ti dico che sto usando una semplificazione e un abuso di linguaggio (e l'ho detto quasi in ogni post di questo thread) non puoi venirmi a dire che rischio che qualcuno pretenda di applicare una cosa che ho espressamente dichiarato non esistere.
e in ogni caso se uno programma in java e pretende che un reference SIA un oggetto non so cosa farci
^TiGeRShArK^
20-01-2008, 02:10
indirizzo, riferimento... mi spieghi la differenza?
perdonami, ma cos'e' un reference se non un L-value di un particolare oggetto?
possibile che non sia ancora chiaro che non sto parlando di come funziona java, ma sto solo rappresentando il passaggio di parametri (nel solo caso in cui essi siano reference type) "immaginando che" il parametro passato sia l'oggetto e non il suo riferimento (chissa' perche' parliamo di riferimento di un oggetto e io non posso usare il termine passaggio per riferimento visto che, anche tecnicamente, cio' che viene passato e' proprio il riferimento all'oggetto, sia pure soltanto per copia...). E' un modo colloquiale di parlare, se vuoi, o di ragionare in termini spiccioli... ancora, e' un modo per identificare il fatto che l'oggetto non e' passato per copia e, visto che di fatto in java non esiste il passaggio per riferimento, parlando di passaggio per riferimento non introduco ambiguita' o possibilita' di fraintendimenti.
allora..
prima di uscire avevo scritto un post piuttosto esplicativo..
ma dato cheu nsimpatico fulmine ha deciso di far andare via la corrente e quel genio di mio fratello ha distrutto il gruppo di continuità si è perso tutto.
Riassumendo in breve :
non esite il termine "concettualmente" o "immaginando che".
Le specifiche del linguaggio java sono ben chiare in proposito.
una variabile, o un l-value se ti piace di + NON è un oggetto.
E' il riferimento di un oggetto, che è cosa ben diversa.
Quando tu passi un parametro ad un metodo passi per copia il suo riferimento.
E tutto ciò è assolutamente lineare ed auto-esplicativo ed elimina ogni possibilità di errore.
Quando tu dici che in java esiste il passaggio per copia dei primitivi e per riferimento dei reference type stai affermando qualcosa che è contrario alle specifiche del linguaggio.
Infatti in java non è mai ammesso il passaggio per riferimento, ma avviene SEMPRE il passaggio per valore.
Quindi il tutto è perfettamente semplice e lineare analizzato in quest'ottica.
Per i primitive type il passaggio per valore implica il passaggio per copia del valore della variabile, nel caso dei reference type avviene sempre il passaggio per copia del valore del riferimento (che è il contenuto della variabile).
Quindi non vedo perchè complicarsi la vita introducento un passaggio per riferimento "fittizio" che non è un vero passaggio per riferimento e che semplicemente, a quanto ci dicono le specifiche del linguaggio, non ha modo di essere e che, in alcuni casi, potrebbe indurre in errore.
^TiGeRShArK^
20-01-2008, 02:12
no? :fagiano:
ma qui non si tratta di semplificare.. al contrario si sta complicando una questione ultrasemplice.
voi dite:
in java i tipi primitivi sono passati per valore mentre gli oggetti sono passati per riferimento (beh ad eccezione degli oggetti immutabili ecc..)
mentre in realtà:
in java tutto viene passato per valore
quale ti sembra più semplice? :fagiano:
quotissimo.
Oltre ad essere una complicazione perchè introduce una disomogeneità nel modo (perfettamente omogeneo) con cui sono trattati i parametri in java, in realtà è anche sbagliato perchè in alcuni casi può portare a errori (come nell'esempio della funzione swap).
e invece no, perche' se ti dico che sto usando una semplificazione e un abuso di linguaggio (e l'ho detto quasi in ogni post di questo thread) non puoi venirmi a dire che rischio che qualcuno pretenda di applicare una cosa che ho espressamente dichiarato non esistere.
e in ogni caso se uno programma in java e pretende che un reference SIA un oggetto non so cosa farci
ma stiamo parlando di programmazione a livello amatoriale o programazione seria? nel secondo caso si commette un errore grossolano a pensare che le variabili contengono gli oggetti. te lo dico perchè ci sono una marea di errori che possono sorgere da queste convinzioni (e sono anche molto difficili da trovare se non si ha la conoscenza di come vanno le cose in realtà).
ma se tu mi dici che non stiamo parlando della realtà ok, non c'è problema. potrei pensare alle variabili come dromedari che contengono un certo valore di liquido nella gobba e questo valore è il contenuto della variabile. il passaggio dei dromedari avviene prendendo un dromedario nuovo e mettendoci nella gobba lo stesso valore di liquido del dromedario originario. :sofico: poi basta che scrivo che pretendo che le variabili siano dromedari che è tutto ok :p
mad_hhatter
20-01-2008, 02:18
no? :fagiano:
ma qui non si tratta di semplificare.. al contrario si sta complicando una questione ultrasemplice.
voi dite:
in java i tipi primitivi sono passati per valore mentre gli oggetti sono passati per riferimento (beh ad eccezione degli oggetti immutabili ecc..)
mentre in realtà:
in java tutto viene passato per valore
quale ti sembra più semplice? :fagiano:
nessuna delle due.
per un principiante la seconda e' molto ambigua: lo puo' portare a pensare che un oggetto sia passato per valore.
ma il punto e' che io non voglio DIRE che gli oggetti sono passati per riferimento, voglio solo poterlo PENSARE mentre ragiono tra me e me o mentre colloquio con qualcuno che conosce java permettendomi di mantenere impliciti alcuni dettagli NOTI.
poi perche' una String o un array non dovrebbero avere lo stesso trattamento? sono passati per copia? assolutamente no, e' solo che ogni metodo della classe String, ad esempio, che abbia lo scopo di modificare una stringa in realta' ritorna un nuovo oggetto String, cosa che, assieme alla semantica dell'operatore = e al fatto che lavoro con reference e non con oggetti, fa si' che un oggetto String sia immutabile... a me pare straordinariamente semplice
mad_hhatter
20-01-2008, 02:19
quotissimo.
Oltre ad essere una complicazione perchè introduce una disomogeneità nel modo (perfettamente omogeneo) con cui sono trattati i parametri in java, in realtà è anche sbagliato perchè in alcuni casi può portare a errori (come nell'esempio della funzione swap).
e infatti e' modo gergale di ragionare (se mi passi l'espressione) che uso io ma che non userei mai se lo scopo fosse quello di essere rigoroso
@mad_hhatter
beh senti nessuno ti vieta di pensare come ti pare, ma nel momento in cui ammetti che quello che pensi non corrisponde alla realtà non vedo perchè continuiamo a discuterne :)
in breve:
esiste il passaggio per riferimento in java? no
posso pensare che esiste comunque? certo, esattamente come puoi pensare che le variabili siano dromedari
mad_hhatter
20-01-2008, 03:39
@mad_hhatter
beh senti nessuno ti vieta di pensare come ti pare, ma nel momento in cui ammetti che quello che pensi non corrisponde alla realtà non vedo perchè continuiamo a discuterne :)
in breve:
esiste il passaggio per riferimento in java? no
posso pensare che esiste comunque? certo, esattamente come puoi pensare che le variabili siano dromedari
beh, io immagino che tu, quando pensi a un oggetto, lo concepisci mentalmente pensando alle locazioni di memoria occupate e al loro contenuto binario... e quando chiami un metodo ti raffiguri tutto lo stack frame corrispondente. giusto?
dai, sul serio, queste prese per i fondelli mi fanno sorridere fino a un certo punto.
ho detto e ripetuto che mi ponevo dal punto di vista dell'oggetto: avete continuato a puntualizzare che cio' che viene passato e' un reference. va bene, vorra' dire che poiche' le specifiche di un linguaggio sono quelle e' vietata qualsiasi rappresentazione informale a solo scopo semplificativo. va beh, prendo atto.
concludendo: in java tutto e' passato per valore...
ah no, scusate, non tutto: gli oggetti no, quelli non vengono passati (giustamente, tanto perche' non mi veniate a dire che che sono convinto che accada il contrario).
ma allora non dovreste aver scritto, per precisione: in java _tutti i parametri_ sono passati per valore? ah, era implicito? eh, ma uno potrebe fraintendere...
epilogo :D
passaggio per riferimento: viene passato l'indirizzo del parametro. punto.
detto questo, in java, volendo capire cosa implica il passaggio di un parametro a un metodo quando il parametro e' un reference type E volendo guardare la cosa dal punto di vista dell'oggetto rappresentato da tale reference, cioe' considerando come parametro l'oggetto piuttosto che il reference, a puro scopo speculativo (analisi lecita, spero, anche se quello che succede veramente coinvolge il reference e non l'oggetto, ma questo e' inessenziale ai fini dell'analisi che sto facendo), ho che al metodo viene passato il reference, cioe' il riferimento, cioe' l'indirizzo dell'oggetto, cioe' l'indirizzo di quella cosa che in questo contesto per me rappresenta il vero parametro (al di la' del fatto che, a rigore, questo sia impreciso).
Toh, guarda... ho descritto, pur in termini puramete concettuali, quello che avviene nel passaggio per riferimento.
Posso allora usare un'espressione colorita e imprecisa a puro scopo di concisione e brevita' discorsiva e dire che "e' come se passassi al metodo l'oggetto per riferimento"?
NO, al massimo mi e' concesso chiamarlo passaggio per indirizzo... che altro non e' se non il riferimento all'oggetto, ma pare che chiamarlo passaggio per riferimento faccia incazzare gli inquilini dell'olimpo.
Insomma, persino quando voglio esplicitamente essere impreciso devo usare delle sottigliezze lessicali... va beh
bon, direi che le cose ce le siamo dette in tutte le salse, siamo ben trincerati nei nostri rispettivi sofismi lessicali pur condividendo che la sostanza, dal punto di vista del linguaggio, e' una sola. ottimo, direi che non c'e' altro da aggiungere, almeno da parte mia.
cdimauro
20-01-2008, 07:07
Scusate se mi intrometto nel forum, ma visto che ho la fortuna di potere chiedere a degli esperti di [Java], volevo sapere secondo la vostra esperienza se in termini di calcolo Moltiplicazioni, divisioni, somme ecc. questo linguaggio, a me sconosciuto, possa essere paragonabile o superiore al [C++] o al [C#]! Vi chiedo questo perchè sono sinceramente interessato al linguaggio ma ho sempre creduto che fosse inferiore in termini di calcolo puro rispetto al [C]! Grazie comunque!:)
Non capisco come ancora si facciano lotte per stabilire qual è il linguaggio più potente, quando la risposta è a dir poco scontata: il linguaggio macchina.
I veri programmatori, quelli duri e puri, quelli che vogliono il massimo senza alcun compromesso, la loro scelta l'hanno già fatta da tempo. Non ci sono storie: non esiste nulla, ma veramente nulla di più potente del linguaggio macchina.
Ovviamente è gente che ha letteralmente divorato tutti questi http://www.intel.com/products/processor/manuals/ manuali, e in particolare quello sulle ottimizzazioni: Intel® 64 and IA-32 Architectures Optimization Reference Manual. Un MUST: non ci si può definire veri programmatori senza averlo digerito.
Poiché i veri programmatori ottimizzano il codice per qualunque processore esistente, altrettanto ovviamente si saranno divorati anche i manuali di AMD: http://developer.amd.com/documentation/guides/Pages/default.aspx Anche qui è un MUST questo: Software Optimization Guide for AMD Athlon™ 64 and AMD Opteron™ Processors
Inutile dire che i veri programmatori non usano nemmeno il notepad per generare gli eseguibili. Infatti aprono un prompt dei comandi, scrivono:
copy con mycoolprogram.exe
e digitano il codice di tutti i byte dell'eseguibile, uno dietro l'altro, utilizzando la famigerata combinazione Alt + tastierino numerico. :cool:
beh, io immagino che tu, quando pensi a un oggetto, lo concepisci mentalmente pensando alle locazioni di memoria occupate e al loro contenuto binario... e quando chiami un metodo ti raffiguri tutto lo stack frame corrispondente. giusto?
dai, sul serio, queste prese per i fondelli mi fanno sorridere fino a un certo punto.
ho detto e ripetuto che mi ponevo dal punto di vista dell'oggetto: avete continuato a puntualizzare che cio' che viene passato e' un reference. va bene, vorra' dire che poiche' le specifiche di un linguaggio sono quelle e' vietata qualsiasi rappresentazione informale a solo scopo semplificativo. va beh, prendo atto.
concludendo: in java tutto e' passato per valore...
ah no, scusate, non tutto: gli oggetti no, quelli non vengono passati (giustamente, tanto perche' non mi veniate a dire che che sono convinto che accada il contrario).
ma allora non dovreste aver scritto, per precisione: in java _tutti i parametri_ sono passati per valore? ah, era implicito? eh, ma uno potrebe fraintendere...
epilogo :D
passaggio per riferimento: viene passato l'indirizzo del parametro. punto.
detto questo, in java, volendo capire cosa implica il passaggio di un parametro a un metodo quando il parametro e' un reference type E volendo guardare la cosa dal punto di vista dell'oggetto rappresentato da tale reference, cioe' considerando come parametro l'oggetto piuttosto che il reference, a puro scopo speculativo (analisi lecita, spero, anche se quello che succede veramente coinvolge il reference e non l'oggetto, ma questo e' inessenziale ai fini dell'analisi che sto facendo), ho che al metodo viene passato il reference, cioe' il riferimento, cioe' l'indirizzo dell'oggetto, cioe' l'indirizzo di quella cosa che in questo contesto per me rappresenta il vero parametro (al di la' del fatto che, a rigore, questo sia impreciso).
Toh, guarda... ho descritto, pur in termini puramete concettuali, quello che avviene nel passaggio per riferimento.
Posso allora usare un'espressione colorita e imprecisa a puro scopo di concisione e brevita' discorsiva e dire che "e' come se passassi al metodo l'oggetto per riferimento"?
NO, al massimo mi e' concesso chiamarlo passaggio per indirizzo... che altro non e' se non il riferimento all'oggetto, ma pare che chiamarlo passaggio per riferimento faccia incazzare gli inquilini dell'olimpo.
Insomma, persino quando voglio esplicitamente essere impreciso devo usare delle sottigliezze lessicali... va beh
bon, direi che le cose ce le siamo dette in tutte le salse, siamo ben trincerati nei nostri rispettivi sofismi lessicali pur condividendo che la sostanza, dal punto di vista del linguaggio, e' una sola. ottimo, direi che non c'e' altro da aggiungere, almeno da parte mia.
allora.. con calma... non era mia intenzione prendere per i fondelli, ma capisci che se la mettiamo sul piano della fantasia non c'è un limite.
devi distinguere la fase di progettazione dalla fase di implementazione IMHO (che non sono necessariamente sequenziali comunque). quando progetto penso agli oggetti in maniera astratta, quando implemento penso a variabili, reference ecc.. altrimenti se continuassi a pensare in maniera astratta produrrei codice prono a errori, cosa da evitare assolutamente.
il fatto che le variabili non contengono oggetti è una cosa che TUTTI i programmatori java devono sapere per poter essere definiti tali, quindi se dico che in java tutto viene passato per valore, dò una definizione che può essere interpretata in una sola maniera, cioè quella corretta.
arrivando al tuo epilogo:
passaggio per riferimento: viene passato l'indirizzo del parametro. punto.
totalmente sbagliato. il passaggio per riferimento NON è quello che hai scritto e aggiungo anche punto (ripeto che la definizione di passaggio per riferimento non l'ho mica inventata io, ma nemmeno te).
nel passaggio per riferimento L-value del parametro coincide con l'L-value della variabile passata come parametro e ho già spiegato che ciò non avviene MAI in java.
Toh, guarda... ho descritto, pur in termini puramete concettuali, quello che avviene nel passaggio per riferimento.
ma dove? hai solo descritto il passaggio di un parametro contenente un indirizzo.
ti ripeto che non è una questione di sottigliezze lessicali, ma proprio di significato. il passaggio per riferimento è quello che puoi fare in C++ punto. quando mi dimostrerai che puoi fare la stessa cosa in java sono pronto a darti ragione.
ps. perchè non potrei scrivere una cosa così altrimenti?
void foo(String string)
{
string = "I was passed by reference :P";
}
non ti sembra che creare fittiziamente una definizione con mille eccezione sia più complicato che pensare alla ultra-semplice realtà dei fatti?
Ma quali sarebbero questi errori dovuti al nostro
scandaloso modo di pensare?
Certo, tutti possono pensarla come vogliono, ma siete voi
che considerate eretico chi dice che "un oggetto viene passato
per riferimento".
Se nelle specifiche non c'è scritto che gli oggetti sono
passati per riferimento non significa che nella realtà
dei fatti non accada proprio questo.
Ringrazio sempre mad_hhatter che sta tenendo duro in mia assenza.
Ma quali sarebbero questi errori dovuti al nostro
scandaloso modo di pensare?
sono già stati fatti alcuni esempi, in ogni caso qualunque persona che ha avuto modo di lavorare su progetti di una certa complessità sa di cosa sto parlando. tipicamente l'errore nasce in presenza di un alias (cioè una variabile che contiene lo stesso riferimento di un'altra variabile). se uno ragiona in termini di oggetti sbaglia, è una cosa provata.
allontanandoci un attimo dal passaggio dei parametri (di cui sono già stati fatti almeno due esempi di possibile errore), un'altro errore potrebbe essere il seguente:
import java.util.ArrayList;
public class Prova {
private ArrayList<Integer> rep;
public static void main(String[] args) {
Prova prova = new Prova();
prova.addNumber(new Integer(1));
prova.addNumber(new Integer(5));
prova.addNumber(new Integer(3));
ArrayList<Integer> numbers = prova.getRep();
numbers.add(new Integer(1));
System.out.println(prova.getRep().toString());
}
public Prova() {
this.rep = new ArrayList<Integer>();
}
public ArrayList<Integer> getRep() {
return this.rep;
}
public void addNumber(Integer number) {
if(!this.rep.contains(number))
this.rep.add(number);
}
public void removeNumber(Integer number) {
this.rep.remove(number);
}
}
tenete conto che questi sono esempi giocattolo e quindi è facile capire perchè non funzionano. nella realtà è molto più difficile perchè queste cose sono immerse nel codice funzionale dell'applicazione.
in pratica questo esempio vi potrà sembrare scemo, ma in situazioni più complesse è di cruciale importanza evitare questi comportamenti.
Certo, tutti possono pensarla come vogliono, ma siete voi
che considerate eretico chi dice che "un oggetto viene passato
per riferimento".
Se nelle specifiche non c'è scritto che gli oggetti sono
passati per riferimento non significa che nella realtà
dei fatti non accada proprio questo.
Ringrazio sempre mad_hhatter che sta tenendo duro in mia assenza.
io non considero affatto eretico chi pensa che gli oggetti siano passati per riferimento, ma semplicemente penso che stiano sbagliando clamorosamente.
le specifiche dicono molto di più, e cioè che _nella realtà dei fatti_ tutto viene passato per valore.
ripeto per l'ennesima volta che il concetto di passaggio per riferimento non l'ho inventato io, al contrario ha una definizione universalmente accettata ben precisa che non è quella di passare per valore un riferimento. quella è un'altra cosa, se volete dategli un altro nome (passaggio per indirizzo ad esempio), ma sappiate che sempre di passaggio per valore di parla.
C++ e C# per esempio hanno il passaggio per riferimento e infatti si comportano in maniera diversa rispetto a java
^TiGeRShArK^
20-01-2008, 13:28
Ma quali sarebbero questi errori dovuti al nostro
scandaloso modo di pensare?
Certo, tutti possono pensarla come vogliono, ma siete voi
che considerate eretico chi dice che "un oggetto viene passato
per riferimento".
Se nelle specifiche non c'è scritto che gli oggetti sono
passati per riferimento non significa che nella realtà
dei fatti non accada proprio questo.
Ringrazio sempre mad_hhatter che sta tenendo duro in mia assenza.
nelle specifiche del linguaggio c'è scritto chiaramente questo:
4.5.3 Kinds of Variables
There are seven kinds of variables:
1. A class variable is a field declared using the keyword static within a class declaration (§8.3.1.1), or with or without the keyword static within an interface declaration (§9.3). A class variable is created when its class or interface is prepared (§12.3.2) and is initialized to a default value (§4.5.5). The class variable effectively ceases to exist when its class or interface is unloaded (§12.7).
2. An instance variable is a field declared within a class declaration without using the keyword static (§8.3.1.1). If a class T has a field a that is an instance variable, then a new instance variable a is created and initialized to a default value (§4.5.5) as part of each newly created object of class T or of any class that is a subclass of T (§8.1.3). The instance variable effectively ceases to exist when the object of which it is a field is no longer referenced, after any necessary finalization of the object (§12.6) has been completed.
3. Array components are unnamed variables that are created and initialized to default values (§4.5.5) whenever a new object that is an array is created (§15.10). The array components effectively cease to exist when the array is no longer referenced. See §10 for a description of arrays.
4. Method parameters (§8.4.1) name argument values passed to a method. For every parameter declared in a method declaration, a new parameter variable is created each time that method is invoked (§15.12). The new variable is initialized with the corresponding argument value from the method invocation. The method parameter effectively ceases to exist when the execution of the body of the method is complete.
5. Constructor parameters (§8.8.1) name argument values passed to a constructor. For every parameter declared in a constructor declaration, a new parameter variable is created each time a class instance creation expression (§15.9) or explicit constructor invocation (§8.8.5) invokes that constructor. The new variable is initialized with the corresponding argument value from the creation expression or constructor invocation. The constructor parameter effectively ceases to exist when the execution of the body of the constructor is complete.
6. An exception-handler parameter is created each time an exception is caught by a catch clause of a try statement (§14.19). The new variable is initialized with the actual object associated with the exception (§11.3, §14.17). The exception-handler parameter effectively ceases to exist when execution of the block associated with the catch clause is complete.
7. Local variables are declared by local variable declaration statements (§14.4). Whenever the flow of control enters a block (§14.2) or for statement (§14.13), a new variable is created for each local variable declared in a local variable declaration statement immediately contained within that block or for statement. A local variable declaration statement may contain an expression which initializes the variable. The local variable with an initializing expression is not initialized, however, until the local variable declaration statement that declares it is executed. (The rules of definite assignment (§16) prevent the value of a local variable from being used before it has been initialized or otherwise assigned a value.) The local variable effectively ceases to exist when the execution of the block or for statement is complete.
quindi non vedo perchè discutere ancora sul sesso degli angeli quando le specifiche del linguaggio sono ben precise in merito.
Poi vi potete fare tutte le rappresentazioni mentali che volete, nessuno ve lo vieta.
Ma, quantomeno non venite a scrivere su un forum pubblico cose del genere:
Vero, primitivi e riferimenti sono passati per valore,
eppure non ho ancora trovato un argomento che mi convinca
che gli oggetti non sono passati per riferimento...
Certo se definisci oggetto = riferimento allora è passato per valore,
se invece lo consideri (come me) qualcosa a cui il riferimento punta
non vedo perché non sia passato per riferimento...
Le tue sono affermazioni assolutistiche che non spiegano/dimostrano/giustificano alcunché.
Magari supporta con qualche argomento l'affermazione "in Java tutto è passato per valore".
Certamente se per "tutto" intendi primitivi e riferimenti hai ragione...
Un riferimento a un oggetto viene passato per valore, su questo non si discute, qui si discute sul passaggio dell'oggetto vero e proprio
Perchè sono completamente errate e possono indurre in confusione chi non ha ben chiaro in testa come funziona il linguaggio Java.
Se poi volete addirittura confutare le specifiche del linguaggio allora create voi un vostro linguaggio e scrivete le specifiche come meglio vi aggrada.
mad_hhatter
20-01-2008, 15:06
import java.util.ArrayList;
public class Prova {
private ArrayList<Integer> rep;
public static void main(String[] args) {
Prova prova = new Prova();
prova.addNumber(new Integer(1));
prova.addNumber(new Integer(5));
prova.addNumber(new Integer(3));
ArrayList<Integer> numbers = prova.getRep();
numbers.add(new Integer(1));
System.out.println(prova.getRep().toString());
}
public Prova() {
this.rep = new ArrayList<Integer>();
}
public ArrayList<Integer> getRep() {
return this.rep;
}
public void addNumber(Integer number) {
if(!this.rep.contains(number))
this.rep.add(number);
}
public void removeNumber(Integer number) {
this.rep.remove(number);
}
}
tenete conto che questi sono esempi giocattolo e quindi è facile capire perchè non funzionano.
scusami eh, ma perche' non dovrebbe funzionare? il risultato e', correttamente, [1,5,3,1] come uno si aspetterebbe leggendo il codice... che c'e' di strano? e guarda caso ne esce che ho modificato un oggetto esistente, come se lo avessi usato per riferimento...
temo di non capire cosa volesse dimostrare quell'esempio.
comunque, visto che evidentemente sono stupido e non capisco, mi spieghi tecnicamente e passo passo cosa succede a livello di stack quando faccio un passaggio per riferimento e quando uso il passaggio per valore di un reference type? cosi' vedo finalmente dove sbaglio.
a tal proposito, citando per l'ennesima volta dal link di ^TiGeRShArK^, http://www.yoda.arachsys.com/java/passing.html:
"reference
The L-value of the formal parameter is set to the L-value of the actual parameter. In other words, the address of the formal parameter is the same as the address of the actual parameter."
saro' anche idiota, ma quando dico:
"passaggio per riferimento: viene passato l'indirizzo del parametro."
non penso di sbagliare... qualcosa viene passato al metodo e quel qualcosa non e' certo il valore del parametro... e allora cosa? se non ne passo l'indirizzo, mi dici cosa usa sto benedetto processore per andare a modificare il parametro?
scusami eh, ma perche' non dovrebbe funzionare? il risultato e', correttamente, [1,5,3,1] come uno si aspetterebbe leggendo il codice... che c'e' di strano? e guarda caso ne esce che ho modificato un oggetto esistente, come se lo avessi usato per riferimento...
Perchè la semantica dell'oggetto "Prova" prevede che l'ArrayList (di Number) "rep" non contenga duplicati (come si vede dal metodo "addNumber"), mentre la semantica della variabile "numbers" non lo prevede affatto. Se sono lo stesso "oggetto", perchè obbediscono a regole diverse? Sarò chiaro a chi legge il codice, ma concettualmente è un pasticcio: che lo stesso "oggetto" ammetta due comportamenti diversi.
mad_hhatter
20-01-2008, 22:05
Perchè la semantica dell'oggetto "Prova" prevede che l'ArrayList (di Number) "rep" non contenga duplicati (come si vede dal metodo "addNumber"), mentre la semantica della variabile "numbers" non lo prevede affatto. Se sono lo stesso "oggetto", perchè obbediscono a regole diverse? Sarò chiaro a chi legge il codice, ma concettualmente è un pasticcio: che lo stesso "oggetto" ammetta due comportamenti diversi.
stesso oggetto? ma stai scherzando? prova e' di tipo Prova, numbers e' di tipo ArrayList<Integer>, perche' mai dovrebbero avere anche solo lontanamente lo stesso comportamento, le stesse semantiche?
scusami eh, ma perche' non dovrebbe funzionare? il risultato e', correttamente, [1,5,3,1] come uno si aspetterebbe leggendo il codice... che c'e' di strano? e guarda caso ne esce che ho modificato un oggetto esistente, come se lo avessi usato per riferimento...
temo di non capire cosa volesse dimostrare quell'esempio.
mixmar l'ha capito, la sua spiegazione è esauriente.
comunque, visto che evidentemente sono stupido e non capisco, mi spieghi tecnicamente e passo passo cosa succede a livello di stack quando faccio un passaggio per riferimento e quando uso il passaggio per valore di un reference type? cosi' vedo finalmente dove sbaglio.
a tal proposito, citando per l'ennesima volta dal link di ^TiGeRShArK^, http://www.yoda.arachsys.com/java/passing.html:
"reference
The L-value of the formal parameter is set to the L-value of the actual parameter. In other words, the address of the formal parameter is the same as the address of the actual parameter."
saro' anche idiota, ma quando dico:
"passaggio per riferimento: viene passato l'indirizzo del parametro."
non penso di sbagliare... qualcosa viene passato al metodo e quel qualcosa non e' certo il valore del parametro... e allora cosa? se non ne passo l'indirizzo, mi dici cosa usa sto benedetto processore per andare a modificare il parametro?
senti.. inizio ad avere seri dubbi sul fatto che leggi i miei commenti. come ho già spiegato prima quello che hai quotato dice:
l'L-value del parametro è lo stesso della variabile che passi come parametro, cioè le due variabili sono la stessa variabile (hanno lo stesso indirizzo).
nel caso di java hanno lo stesso contenuto, ma non lo stesso indirizzo, perciò non è passaggio per riferimento.
mad_hhatter
20-01-2008, 22:40
mixmar l'ha capito, la sua spiegazione è esauriente.
leggi la mia risposta al suo post
senti.. inizio ad avere seri dubbi sul fatto che leggi i miei commenti. come ho già spiegato prima quello che hai quotato dice:
l'L-value del parametro è lo stesso della variabile che passi come parametro, cioè le due variabili sono la stessa variabile (hanno lo stesso indirizzo).
nel caso di java hanno lo stesso contenuto, ma non lo stesso indirizzo, perciò non è passaggio per riferimento.
ma allora non ci capiamo! io sto parlando dell'oggetto!!! e' chiaro che se consideri il fatto che passi un reference type e lo passi per valore il parametro formale e quello "actual" hanno indirizzi differenti, questo nessuno mai lo ha messo in dubbio in questo thread. MA se io voglio pormi dal punto di vista dell'oggetto rappresentato da questo benedetto reference type allora si' che formal e actual parater hanno lo stesso indirizzo (per forza, uso due reference type che sono uno la copia dell'altro e quindi puntano allo stesso oggetto). quindi se io considero essere l'oggetto il parametro, sempre solo a livello concettuale, il comportamento che ottengo e' analogo al passaggio per riferimento (ripeto, considerando come parametro l'oggetto)
saro' anche idiota, ma quando dico:
"passaggio per riferimento: viene passato l'indirizzo del parametro."
non penso di sbagliare... qualcosa viene passato al metodo e quel qualcosa non e' certo il valore del parametro... e allora cosa? se non ne passo l'indirizzo, mi dici cosa usa sto benedetto processore per andare a modificare il parametro?
e invece sbagli perchè nella definizione che tu stesso hai quotato non c'è scritto da nessuna parte che viene passato l'indirizzo della variabile.
nel passaggio per riferimento il parametro è la variabile che passi come parametro. sono proprio la stessa area di memoria, stesso L-value.
mad_hhatter
20-01-2008, 22:44
e invece sbagli perchè nella definizione che tu stesso hai quotato non c'è scritto da nessuna parte che viene passato l'indirizzo della variabile.
nel passaggio per riferimento il parametro è la variabile che passi come parametro. sono proprio la stessa area di memoria, stesso L-value.
e come la identifichi questa benedetta area di memoria se non tramite il suo indirizzo? se vuoi che il metodo lavori con quella stessa identica area di memoria dovrai passargli il suo indirizzo, no? altrimenti cosa gli passi? o gli passi il valore o gli passi l'indirizzo... nel primo caso non usi la stessa area di memoria, quindi fai te... o ci sono altre alternative?
e, esattamente come hai detto tu, quando considero il passaggio "concettuale" di un oggetto ottengo che il metodo lavora con lo stesso oggetto puntato dal reference passato come parametro. guarda un po', proprio come da te descritto a proposito del passaggio per riferimento
se mi spiegassi cosa accade sullo stack forse ci capiremmo una volta per tutte
leggi la mia risposta al suo post
il suo post è chiaro. come è evidente dal metodo addNumber nell'ArrayList non dovrebbero esserci elementi duplicati, ma a causa del fatto che considero le cose a livello di oggetti astratti non mi rendo conto che restituendo l'oggetto "rep" espongo la rappresentazione dell'oggetto "prova". e come conseguenza posso inserire elementi duplicati in prova.
uno che pensa in termini di riferimenti non avrebbe mai scritto una porcheria simile.
ma allora non ci capiamo! io sto parlando dell'oggetto!!! e' chiaro che se consideri il fatto che passi un reference type e lo passi per valore il parametro formale e quello "actual" hanno indirizzi differenti, questo nessuno mai lo ha messo in dubbio in questo thread. MA se io voglio pormi dal punto di vista dell'oggetto rappresentato da questo benedetto reference type allora si' che formal e actual parater hanno lo stesso indirizzo (per forza, uso due reference type che sono uno la copia dell'altro e quindi puntano allo stesso oggetto). quindi se io considero essere l'oggetto il parametro, sempre solo a livello concettuale, il comportamento che ottengo e' analogo al passaggio per riferimento (ripeto, considerando come parametro l'oggetto)
il passaggio dei parametri coinvolge sole variabili. una volta appurato che le variabili non contengono mai oggetti il resto del tuo discorso è privo di senso.
e come la identifichi questa benedetta area di memoria se non tramite il suo indirizzo? se vuoi che il metodo lavori con quella stessa identica area di memoria dovrai passargli il suo indirizzo, no? altrimenti cosa gli passi? o gli passi il valore o gli passi l'indirizzo... nel primo caso non usi la stessa area di memoria, quindi fai te... o ci sono altre alternative?
e, esattamente come hai detto tu, quando considero il passaggio "concettuale" di un oggetto ottengo che il metodo lavora con lo stesso oggetto puntato dal reference passato come parametro. guarda un po', proprio come da te descritto a proposito del passaggio per riferimento
se mi spiegassi cosa accade sullo stack forse ci capiremmo una volta per tutte
ma chissenefrega di cosa succede nello stack dico io :D
il compilatore gestirà in maniera opportuna questa cosa.. l'importante è che il parametro abbia lo stesso L-value della variabile che passi come parametro. se è così stiamo parlando di passaggio per riferimento.
il "passaggio concettuale" degli oggetti l'hai inventato tu, perciò non so cosa dirti. l'unica cosa certa è che non si tratta di passaggio di parametri per riferimento, perchè quello non l'hai inventato te ed ha una definizione ben precisa
mad_hhatter
20-01-2008, 23:31
il suo post è chiaro. come è evidente dal metodo addNumber nell'ArrayList non dovrebbero esserci elementi duplicati, ma a causa del fatto che considero le cose a livello di oggetti astratti non mi rendo conto che restituendo l'oggetto "rep" espongo la rappresentazione dell'oggetto "prova". e come conseguenza posso inserire elementi duplicati in prova.
uno che pensa in termini di riferimenti non avrebbe mai scritto una porcheria simile.
ah si'? e perche' mai pensare in termini di riferimenti avrebbe impedito di esporre quella che tu chiami rappresentazione dell'oggetto prova? giuro che non vedo il nesso. gradirei una dimostrazione di quanto hai appena affermato.
in ogni caso rep NON e' la rappresentazione di prova: prova contiene un arrayList, rep e' un arrayList... ti sembra la stessa cosa? anche ragionando in termini astratti sono 2 oggetti completamente diversi che espongono 2 comportamenti assolutamente diversi.
il passaggio dei parametri coinvolge sole variabili. una volta appurato che le variabili non contengono mai oggetti il resto del tuo discorso è privo di senso.
ancora? ma possibile che debba ripeterlo in ogni singolo post?! voglio considerare la cosa dal punto di vista dell'oggetto rappresentato da una variabile!!! e' una analisi illecita per caso?
ma chissenefrega di cosa succede nello stack dico io :D
il compilatore gestirà in maniera opportuna questa cosa.. l'importante è che il parametro abbia lo stesso L-value della variabile che passi come parametro. se è così stiamo parlando di passaggio per riferimento.
il "passaggio concettuale" degli oggetti l'hai inventato tu, perciò non so cosa dirti. l'unica cosa certa è che non si tratta di passaggio di parametri per riferimento, perchè quello non l'hai inventato te ed ha una definizione ben precisa
io non devo e non voglio inventare nulla... sto soltanto analizzando un comportamento.
e' proprio cercando di analizzare cosa avviene sullo stack che mi porta a discutere del fatto che e' come se l'oggetto venisse passato per riferimento!
avanti, ancora una volta... dal solito link:
"reference
The L-value of the formal parameter is set to the L-value of the actual parameter. In other words, the address of the formal parameter is the same as the address of the actual parameter. Any modifications to the formal parameter also immediately affect the actual parameter. FORTRAN only has reference mode (expressions are evaluated and stored in a temporary location in order to obtain an L-value). C++ has reference parameters by putting a & before the formal parameter name in the function header. Reference mode can be simulated in C using pointers and adding the & to the actual parameter and dereferencing the formal parameter within the function."
toh guarda, anche quel link super rigoroso adotta un'espressione che suona come un "e' come se"... la consideri un'imperdonabile fonte di fraintendimenti ed errori anche quella?
ma quello che mi preme e': se considero per un momento l'oggetto, non la variabile, come parametro ho proprio che copiando il valore del reference type si ha la situazione in cui "the address of the formal parameter is the same as the address of the actual parameter" dove, ripeto, parameter qui indico (io, volutamente, cosciente del fatto che tecnicamente cio' non corrisponde a quello che realmente viene passato) l'oggetto, non la variabile. neghi che cio' sia vero?
in alternativa rispondi a questa domanda:
sia b un oggetto, di tipo B, rappresentato dal riferimento rb e sia f(B p) un metodo.
dei tipi di passaggio di parametri elencati al solito link, quale descrive la relazione tra p e b quando invoco f(rb)?
ancora? ma possibile che debba ripeterlo in ogni singolo post?! voglio considerare la cosa dal punto di vista dell'oggetto rappresentato da una variabile!!! e' una analisi illecita per caso?
nel caso del passaggio di parametri sì. perchè i parametri sono variabili.
potresti definire il passaggio di oggetti, ma di sicuro se parliamo di passaggio di parametri (e in questo thread è quello che stiamo facendo) stiamo parlando di variabili e quindi non di oggetti (nel caso di java).
io non devo e non voglio inventare nulla... sto soltanto analizzando un comportamento.
e' proprio cercando di analizzare cosa avviene sullo stack che mi porta a discutere del fatto che e' come se l'oggetto venisse passato per riferimento!
avanti, ancora una volta... dal solito link:
"reference
The L-value of the formal parameter is set to the L-value of the actual parameter. In other words, the address of the formal parameter is the same as the address of the actual parameter. Any modifications to the formal parameter also immediately affect the actual parameter. FORTRAN only has reference mode (expressions are evaluated and stored in a temporary location in order to obtain an L-value). C++ has reference parameters by putting a & before the formal parameter name in the function header. Reference mode can be simulated in C using pointers and adding the & to the actual parameter and dereferencing the formal parameter within the function."
toh guarda, anche quel link super rigoroso adotta un'espressione che suona come un "e' come se"... la consideri un'imperdonabile fonte di fraintendimenti ed errori anche quella?
ma quello che mi preme e': se considero per un momento l'oggetto, non la variabile, come parametro ho proprio che copiando il valore del reference type si ha la situazione in cui "the address of the formal parameter is the same as the address of the actual parameter" dove, ripeto, parameter qui indico (io, volutamente, cosciente del fatto che tecnicamente cio' non corrisponde a quello che realmente viene passato) l'oggetto, non la variabile. neghi che cio' sia vero?
in alternativa rispondi a questa domanda:
sia b un oggetto, di tipo B, rappresentato dal riferimento rb e sia f(B p) un metodo.
dei tipi di passaggio di parametri elencati al solito link, quale descrive la relazione tra p e b quando invoco f(rb)?
simulare non vuol dire essere. proprio dal fatto che c'è scritto che in C si può "simulare" il passaggio per riferimento si capisce che in C non esiste il passaggio per riferimento. per java è la stessa cosa.
per rispondere all'ultima tua domanda:
immagino che è sottointeso che parliamo di java, quindi senza ombra di dubbio passaggio per valore.
mad_hhatter
21-01-2008, 00:00
nel caso del passaggio di parametri sì. perchè i parametri sono variabili.
potresti definire il passaggio di oggetti, ma di sicuro se parliamo di passaggio di parametri (e in questo thread è quello che stiamo facendo) stiamo parlando di variabili e quindi non di oggetti (nel caso di java).
simulare non vuol dire essere. proprio dal fatto che c'è scritto che in C si può "simulare" il passaggio per riferimento si capisce che in C non esiste il passaggio per riferimento. per java è la stessa cosa.
per rispondere all'ultima tua domanda:
immagino che è sottointeso che parliamo di java, quindi senza ombra di dubbio passaggio per valore.
:D colpa mia, colpa mia... devo ricordarmi di essere rigoroso: riformulo la domanda:
sia b un oggetto, di tipo B, rappresentato dal riferimento rb e sia f(B p) un metodo.
dei tipi di passaggio di parametri elencati al solito link, quale descrive la relazione tra l'oggetto rappresentato da p e l'oggetto b quando invoco f(rb)?
certo simulare non significa essere, appunto per questo ho sempre aggiunto le espressioni "e' come se", "concettualmente", "abuso di notazione", "ragionamento astratto". non sto analizzando cosa e' in java, sto analizzando come si puo' concettualizzare (a puro scopo di analisi) in maniera alternativa un aspetto molto particolare e circoscritto.
resto in attesa della dimostrazione che ragionare in termini di riferimenti impedisce errori come quello descritto nell'esempio visto in precedenza (posto che si possa parlare di errore visto che si sono usati due oggetti completamenti diversi di proposito)
PS: @lovaz: sono quasi allo stremo delle forze :D
:D colpa mia, colpa mia... devo ricordarmi di essere rigoroso: riformulo la domanda:
sia b un oggetto, di tipo B, rappresentato dal riferimento rb e sia f(B p) un metodo.
dei tipi di passaggio di parametri elencati al solito link, quale descrive la relazione tra l'oggetto rappresentato da p e l'oggetto b quando invoco f(rb)?
ho già risposto che è passaggio per valore, comunque commetti un errore di fondo perchè il passaggio dei parametri agisce sulle variabili, quindi non sugli oggetti. ancora una volta.. se vuoi inventare la definizione di passaggio di oggetti non so cosa dirti. ma per favore non chiamarlo passaggio di parametri per riferimento, perchè quella è un'altra cosa
certo simulare non significa essere, appunto per questo ho sempre aggiunto le espressioni "e' come se", "concettualmente", "abuso di notazione", "ragionamento astratto". non sto analizzando cosa e' in java, sto analizzando come si puo' concettualizzare in maniera alternativa un aspetto molto particolare e circoscritto.
simulare non è equivalente a "è come se", "concettualmente" ecc..
infatti il passaggio dei parametri usato da java per gli oggetti non è come se fosse per riferimento, altrimenti potresti fare le cose che fai in C++ (vedi esempi nelle pagine precedenti). e non è nemmeno concettualmente la stessa cosa visto che si parla di riferimenti passati per valore mentre tu dici che gli oggetti sono passati per riferimento. è proprio un concetto diverso
PS: @lovaz: sono quasi allo stremo delle forze :D
e non sei l'unico :D
tiger help meeeeee!! :fagiano:
cdimauro
21-01-2008, 08:00
6 pagine per discutere sul passaggio di parametri in Java?
E' per valore. E' scritto nelle specifiche. E' così che lavora il compilatore.
Fine della questione.
^TiGeRShArK^
21-01-2008, 08:45
6 pagine per discutere sul passaggio di parametri in Java?
E' per valore. E' scritto nelle specifiche. E' così che lavora il compilatore.
Fine della questione.
:muro:
è da tempo immemore che sto cercando di farglielo capire...
e il bello è che mi sono dovuto anche smazzare le specifiche per quotare il punto esatto dove veniva enunciato dato che ancora questi insistono che nelle specifiche non è scritto in nessun posto..
E dopo averlo riportato quanti hai visto che hanno quotato il mio messaggio?
NESSUNO.
Continuano ad interpretare MALE quanto scritto nei due link che avevo postato precedentemente senza cercare di capirne le parole nell'ottica di quanto scritto nelle specifiche, ovvero:
4. Method parameters (§8.4.1) name argument values passed to a method. For every parameter declared in a method declaration, a new parameter variable is created each time that method is invoked (§15.12). The new variable is initialized with the corresponding argument value from the method invocation. The method parameter effectively ceases to exist when the execution of the body of the method is complete.
Non c'è altro da aggiungere.
Tradotto in italiano, nel caso fosse questa la difficoltà, le specifiche dicono chiaramente che:
Per ogni parametro dichiarato nella signature di un metodo, viene creata una variabile a seguito di ogni invocazione. La nuova variabile è quindi inizializzata con il corrispondente valore ricevuto dall'invocazione del metodo (viene effettuata una copia N.D.T.). Il parametro del metodo cessa definitivamente di esistere alla conclusione del esecuzione del corpo del metodo.
Quindi il passaggio per riferimento non esiste, ma, al massimo, solo ed esclusivamente per i reference type, esiste il passaggio per copia del riferimento, che è cosa semanticamente differente.
E dopo questo spero sia chiaro perchè, sinceramente, meglio delle specifiche del linguaggio Java non lo so spiegare.
cdimauro
21-01-2008, 08:56
Chiarissimo e d'accordissimo. Anzi, per me è a dir poco lapalissiano. Spero che la cosa finisca qui, perché, davvero non ha proprio senso continuare.
Sui reference... beh... sono valori. :D
Le variabili definite con tipi "standard" contengono dati "standard"? Va benissimo. Sono valori / dati.
Le variabili definite come istanze contengo l'indirizzo dell'area di memoria allocata per l'oggetto. E' un dato? Sì. Va benissimo anche questo. Sono valori / dati.
In entrambi i casi, quando vengono passate come parametri, cosa si fa? Una COPIA del valore. Che corrisponde al dato "standard" nel primo caso, e all'indirizzo dell'area di memoria nel secondo caso. Ma sempre una COPIA DEL VALORE CONTENUTO NELLA VARIABILE è!
A meno che non si debba considerazione come "valore" un indirizzo di memoria, ma a questo punto vorrei capire la differenza fra copiare i 4 byte di un intero a 32 bit e copiare i 4 byte di un indirizzo di memoria (su macchine a 32 bit) quando un oggetto "reference" viene passato come parametro.
Vorrei capirlo perché, se non è così, credo di avere evidenti difficoltà cognitive, e ho bisogno di essere illuminato. :p
mad_hhatter
21-01-2008, 09:11
@^TiGeRShArK^
io non ho bisogno di quotare le tue citazioni dalle specifiche del ling java: so benissimo che in java il passaggio dei parametri è esclusivamente per valore, come ho più volte puntualizzato nei miei post.
se non è ancora chiaro qual è il punto di vista da cui sto considerando la faccenda non so cosa farci, làho già ripetuto fino alla nausea.
se non è ancora chiaro non sto tentando di dare una nuova definizione di cose già perfettamente definite, sto soltanto facendo delle considerazioni. se tu a queste considerazioni mi rispondi con le spec sulle quali siamo già tutti in accordo non so cosa ti aspetti che ti risponda
@cdimauro
non sto discutendo delle specifice, sto facendo un'analisi sull'implicazione di tali specifiche quando si consideri non il reference type ma l'oggetto da esso rappresentato.
@tutti
comincio a chiedermi a che pro continuare a discutere visto che proseguiamo su 2 binari che non sembrano avere possibilità di incontrarsi
^TiGeRShArK^
21-01-2008, 09:21
Ok...
allora quando parliamo di qualcosa è inutle appellarsi alle specifiche...
E' un pò come dire........
dissertare sulla caduta dei gravi senza considerare la forza di gravità.
Se noi usiamo uno strumento, mi pare il minimo attenersi alle specifiche di quello strumento quando si fa una discussione, altrimenti tutti potrebbero iniziare a dire cose senza senso.
Stai facendo praticametne lo stesso discorso dell'Intelligent Design quando non consideri le specifiche.
Poichè ottieni quel risultato allora *potrebbe essere che*, *concettualmente avviene* e cose del genere.
Ma quelle sono solo rappresentazioni ipotetiche del problema che non hanno alcuna attinenza con la realtà.
Esattamente come la teoria del Flying Spaghetti Monster che ha la stessa valenza dell'Intelligent Design.
La realtà è una: In java esiste solo ed esclusivametne il passaggio per valore.
Poi tu e lovaz potete pensarla come volete, siete liberissimi di farlo.
Basta che non scrivete il vostro personale pensiero su un forum pretendendo che vi sia dato credito maggiore rispetto alle specifiche del linguaggio java, che, a quanto ne so, non avete scritto voi.
mad_hhatter
21-01-2008, 09:53
se non è ancora chiaro non sto tentando di dare una nuova definizione di cose già perfettamente definite, sto soltanto facendo delle considerazioni. se tu a queste considerazioni mi rispondi con le spec sulle quali siamo già tutti in accordo non so cosa ti aspetti che ti risponda
Ok...
allora quando parliamo di qualcosa è inutle appellarsi alle specifiche...
E' un pò come dire........
dissertare sulla caduta dei gravi senza considerare la forza di gravità.
Se noi usiamo uno strumento, mi pare il minimo attenersi alle specifiche di quello strumento quando si fa una discussione, altrimenti tutti potrebbero iniziare a dire cose senza senso.
Stai facendo praticametne lo stesso discorso dell'Intelligent Design quando non consideri le specifiche.
Poichè ottieni quel risultato allora *potrebbe essere che*, *concettualmente avviene* e cose del genere.
Ma quelle sono solo rappresentazioni ipotetiche del problema che non hanno alcuna attinenza con la realtà.
Esattamente come la teoria del Flying Spaghetti Monster che ha la stessa valenza dell'Intelligent Design.
La realtà è una: In java esiste solo ed esclusivametne il passaggio per valore.
Poi tu e lovaz potete pensarla come volete, siete liberissimi di farlo.
Basta che non scrivete il vostro personale pensiero su un forum pretendendo che vi sia dato credito maggiore rispetto alle specifiche del linguaggio java, che, a quanto ne so, non avete scritto voi.
cosa della frase che ho riportato in alto non ti è chiaro, al punto da continuare ad accusarmi di voler ridefinire una specifica?
non ho scritto io le specifiche: ovvio. Ma posso analizzarle secondo un dato punto di vista a scolo scopo d'indagine o le specifiche vanno prese come itestimoni di Geova prendono la Bibbia?
OT:
nelle scienze fisiche e naturali si usano spesso modelli concettuali che non hanno realtà sostanziale (si veda la teoria corpuscolare/ondulatoria della luce, il concetto di momento di una forza, tanto per citarne un paio)... questi modelli non descrivono la realtà, aiutano a comprenderla, a concepirla.
Perché è tanto scadaloso fare la stessa cosa con un linguaggio di programmazione e neanche con lo scopo di descrivere un aspetto di tale linguaggio, ma soltanto al fine di discorrerne in maniera informale?
cosa della frase che ho riportato in alto non ti è chiaro, al punto da continuare ad accusarmi di voler ridefinire una specifica?
non ho scritto io le specifiche: ovvio. Ma posso analizzarle secondo un dato punto di vista a scolo scopo d'indagine o le specifiche vanno prese come itestimoni di Geova prendono la Bibbia?
Le specifiche del linguaggio vanno prese esattamente come la Bibbia :)
Dal leggere la discussione mi sembra che tu abbia fatto un'affermazione rivelatasi scorretta e/o imprecisa e invece di ammetterlo candidamente tu stia cercando di giustificarla in qualche modo, arrampicandoti sugli specchi.
Java passa tutti i parametri per valore. Fine della questione.
mad_hhatter
21-01-2008, 10:26
Le specifiche del linguaggio vanno prese esattamente come la Bibbia :)
Dal leggere la discussione mi sembra che tu abbia fatto un'affermazione rivelatasi scorretta e/o imprecisa e invece di ammetterlo candidamente tu stia cercando di giustificarla in qualche modo, arrampicandoti sugli specchi.
Java passa tutti i parametri per valore. Fine della questione.
ti sembra che in qualche post io abbia voluto far passare l'idea che il passaggio di parametri (parametri reali, cioè reference type e primitive type) avvenga secondo modalità diverse da quella per valore?
non ho forse sempre insistito sul fatto che consideravo l'oggetto, non il reference type ad esso corrispondente?
non ho forse insistito sul fatto che era, la mia, una dissertazione concettuale?
ho forse mai messo in discussione le specifiche?
è probabile che nei primi post abbia peccato di imprecisione, ma mi pare di essermi sbrigato a chiarire... se questo è arrampicarsi sugli specchi.
ti ringrazio per la scarsa onestà intellettuale che mi attribuisci.
PS: @lovaz: sono quasi allo stremo delle forze :D
Ti capisco... :D
Visto che ognuno è arroccato sulle sue posizioni io mi ritiro, ho altro da fare
in questo periodo, queste discussioni portano via un sacco di tempo ed
energie nervose.
Ma voi continuate pure se volete, eh...
@tiger et altri:
Ho letto quel pezzo delle specifiche, non contrasta con quanto
ho detto io fin dall'inizio, ma comunque non ti convincerò mai, quindi...
Il fatto dell'aliasing appare chiarissimo praticamente a tutti, in vari
libri/tutorial/corsi viene chiarito che un riferimento punta a un oggetto
e che questo riferimento viene copiato all'interno del metodo, e
che questa copia scompare all'uscita, quindi chi fa questi errori
o lo fa per distrazione, o perche' non ha capito questo...
Le altre affermazioni tipo "è così e basta" non le commento neanche.
Fine delle trasmissioni.
astorcas
21-01-2008, 11:55
Ti capisco... :D
Visto che ognuno è arroccato sulle sue posizioni io mi ritiro, ho altro da fare
in questo periodo, queste discussioni portano via un sacco di tempo ed
energie nervose.
Ma voi continuate pure se volete, eh...
@tiger et altri:
Ho letto quel pezzo delle specifiche, non contrasta con quanto
ho detto io fin dall'inizio, ma comunque non ti convincerò mai, quindi...
Il fatto dell'aliasing appare chiarissimo praticamente a tutti, in vari
libri/tutorial/corsi viene chiarito che un riferimento punta a un oggetto
e che questo riferimento viene copiato all'interno del metodo, e
che questa copia scompare all'uscita, quindi chi fa questi errori
o lo fa per distrazione, o perche' non ha capito questo...
Le altre affermazioni tipo "è così e basta" non le commento neanche.
Fine delle trasmissioni.
Finora ho preferito solo leggere ma ora vorrei dire la mia:
Premettendo che sono del partito "JAVA passa parametri per valore" e che il post http://www.hwupgrade.it/forum/showpost.php?p=20634729&postcount=47 non poteva spiegarlo meglio provo a fare capire perchè tutto ciò è vero:
Creo un oggetto:
Object x=new Object();
x.a=5; //supponiamo che a e b esistano e siano interi
x.b=6; //
supponiamo che punti alla posizione di memoria MILLEMILA
Ora creo il metodo e per parametro gli passo oggetto
void metodo_cambia_a_b(Object obj){
obj.a= 100;
obj.b= 200;
}
Invoco il metodo:
metodo_cambia_a_b(x);
ora stampo i valori
System.out.println(x.a);
System.out.println(x.b);
Oh caspita "a" e "b" sono diventati 100 e 200...
Questo è un passaggio per riferimento?
NO! x punta e punterà sempre all'indirizzo MILLEMILA e non c'è metodo che possa fare la magia!
ERGO: JAVA non ha il passaggio per riferimento nemmeno concettualmente!
ti sembra che in qualche post io abbia voluto far passare l'idea che il passaggio di parametri (parametri reali, cioè reference type e primitive type) avvenga secondo modalità diverse da quella per valore?
non ho forse sempre insistito sul fatto che consideravo l'oggetto, non il reference type ad esso corrispondente?
non ho forse insistito sul fatto che era, la mia, una dissertazione concettuale?
ma non puoi considerare gli oggetti, stiamo parlando di passaggio di parametri, lo sai leggere il titolo della discussione? gli oggetti non sono parametri, ma lo sono i loro riferimenti, quindi tutte le tue considerazioni sono sbagliate.
e non è nemmeno "come se fosse" perchè ti ho già fatto degli esempi in C++ che non è possibile riprodurre in java semplicemente perchè C++ ha il passaggio per riferimento, mentre java no.
nessuno ti impedisce di inventare tutte le definizioni che vuoi, ma non puoi ridefinire il concetto di passaggio per riferimento come ti pare, perchè quello è già stato definito ed è universalmente accettato. se proprio chiamalo passaggio per indirizzo come ho letto in qualche articolo su internet, ecco questo lo posso anche accettare perchè non crea confusione con il passaggio per riferimento che è tutta un'altra cosa. anche se poi bisogna ricordarsi che il passaggio per indirizzo non è altro che il passaggio per valore di un indirizzo.
primesinp
21-01-2008, 13:06
ualcuno mi spiega in soldoni cosa vuol dire che in java "i parametri vengono passati per valore"??
Grazie :)
In soldoni: ogni variabile è composta da due "campi": L-valore e R-valore (left, right, rispettivamente).
L-valore contiene l'indirizzo di RAM dove si trova (in realtà, inizia...) l'R-valore
R-valore contiene il valore "vero e proprio" della variabile
Ora, in JAVA:
- le variabili di tipo primitivo hanno nell'R-valore il "valore" della variabile;
- le variabili di tipo oggetto hanno nell'R-valore l'indirizzo della prima parola in RAM dell'area di memoria che contiene i bit che rappresentano l'oggetto;
- l'L-valore di una variabile non è MAI ACCESSIBILE al programmatore;
- è accessibile R-valore di una variabile di tipo oggetto (e questo int rappresenta effettivamente un indirizzo di memoria)
Quando si dice che in JAVA tutti i parametri sono passati per valore, si intende che:
- per variabili di tipo primitivo, è effettuata la COPIA del valore effettivo (quindi, l'R-valore);
- per variabili di tipo oggetto, è effettuata la COPIA dell'indirizzo della prima parola in RAM dell'area di memoria che contiene i bit che rappresentano l'oggetto (quindi, ancora l'R-valore)
Ora, cara blue_blue, ti dovrei tirare le orecchie... perché queste cose potevi chiederle al TJ ... :D
blue_blue
21-01-2008, 13:20
primesinp, hai pm :D
Ciao a tutti.
La lettura di questi thread e dei i link segnalati è stata molto interessante.
Lo riapro perchè mi è venuto un dubbio:
public class Main {
public static void main(String[] args) {
Integer a = 0;
Integer[] riferimento =new Integer[1];
riferimento[0] = a;
prova(riferimento);
System.out.println(riferimento[0]);
}
private static void prova(Integer[] riferimento) {
riferimento[0] = 1;
}
}
Questo codice simula un passaggio per riferimento.
La modifica dell'array all'interno del metodo prova è visibile
all'esterno, cioè nel main.
Perchè?
Saluti
primesinp
10-09-2008, 18:34
La modifica dell'array all'interno del metodo prova è visibile
all'esterno, cioè nel main.
Perchè?
Perché dell'array viene passato l'indirizzo della prima locazione in memoria che contiene la cella di indice 0. La funzione ne modifica il contenuto e termina. Di conseguenza, quando il main continua e recupera il valore della cella d'indice 0, legge il valore modificato.
Faccio notare che usare array di Integer (oggetti) oppure array di int (tipo primitivo) è indifferente, ai fini dell'esempio.
khelidan1980
24-04-2010, 15:48
come ho avuto modo già di dire nell'altra discussione, dove ho chiesto un chiarimento sulla creazione degli oggetti, mi sono incasinato con il passaggio di parametri per valore.
questa ( http://img202.imageshack.us/img202/9826/immaginexr.jpg ) è un'immagine presa dal manuale dal quale sto studiando ("Object Oriented && Java 5" -> pagina 101 | scaricabile gratuitamente da http://www.claudiodesio.com/).
non riesco proprio a capire dove inserire quella creazione dell'oggetto (prima riga del secondo riquadro) e soprattutto cosa significa ogg.cambiaValore(numero);.
se mi spiegate questa cosa in termini terra terra ve ne sono grato visto che sono di coccio e non riesco a capire questa cosa.
forse sarebbe meglio se mi scriveste il codice che vedete nell'immagine in maniera ordinata perchè così, a pezzi, non riesco a capire la corretta posizione del frammento di codice.
quì ti sta spiegando che il passaggio di parametri in java avviene per copia, ma se non hai capito la sintassi di quello che hai scritto in grassetto ti consiglio di tornare indietro e rileggerti le parti precedenti del libro, in parole povere sta chiamando il metodo cambiaValore sull'ooggetto ogg che ha precedentemente istanziato
nuovoUtente86
26-04-2010, 10:27
quindi in sostanza sarebbe:
nomeOggetto.nomeMetodo;
dove per nomeOggetto intendo quello creato nella classe in cui si sta lavorando mentre per nomeMetodo intendo il metodo dichiarato nell'altra classe di cui però si vuole passare il valore. dico bene? ditemele se dico castronerie.:)
nomeOggetto è un' istanza della classe in cui è definito nomeMetodo, che vai ad invocare, appunto, su quel particolare oggetto, il che sta a dire che se la classe è ben progettata, la reazione a tale invocazione dipenderà dallo stato interno attuale dell' oggetto.
nuovoUtente86
26-04-2010, 10:28
quì ti sta spiegando che il passaggio di parametri in java avviene per copia, ma se non hai capito la sintassi di quello che hai scritto in grassetto ti consiglio di tornare indietro e rileggerti le parti precedenti del libro, in parole povere sta chiamando il metodo cambiaValore sull'ooggetto ogg che ha precedentemente istanziato
In realtà in java il passaggio è per valore per i tipi primitivi, mentre è per "copia di reference" per i tipi oggetto.
questo è uno degli esercizi del libro:
quando nel main della classe Principale va a stampare va a richiamare il metodo dettagli della classe Persona e quindi anche quello è un passaggio per valore. o no? non vorrei aver capito male.
Gli oggetti vengono sempre passati per riferimento.
Il metodo "dettagli" restituisce un reference ad un oggetto di tipo String.
nuovoUtente86
26-04-2010, 11:07
questo è uno degli esercizi del libro:
quando nel main della classe Principale va a stampare va a richiamare il metodo dettagli della classe Persona e quindi anche quello è un passaggio per valore. o no? non vorrei aver capito male.
prima dell' invocazione della stampa viene costruita una nuova stringa composta dalla parte letterale alla sinistra dell' operatore di concatenazione (+) e dalla parte a destra derivante dalla chiamata di dettagli(). Al metodo print viene passata una copia del riferimento a tale stringa. Le modifiche attuate attraverso tale riferimento si riflettono sull' oggetto reale (in realtà per le stringhe è un po diversa la situazione perchè si tratta di oggetti immutabili), mentre eventuali assegnamenti non modificano il riferimento originale .
nuovoUtente86
26-04-2010, 11:08
Gli oggetti vengono sempre passati per riferimento.
Il metodo "dettagli" restituisce un reference ad un oggetto di tipo String.
"Copia di reference" e riferimento non sono la stessa cosa: nel primo caso non è possibile interrompere il riferimento originale, nel secondo si.
nuovoUtente86
26-04-2010, 11:49
vediamo se ho capito. supponiamo di creare una classe avente al suo interno un certo metodo (es. public void cambiaValore(int valore);) e al suo interno dichiariamo una variabile (es. valore = 1000;).
in seguito andiamo a creare un'altra classe, al suo interno andiamo a creare un oggetto e andiamo a dichiarare una variabile (es. int numero = 10;).
a questo punto se volessimo passare per valore il contenuto della variabile numero dovremmo scrivere:
nomeOggetto.cambiaValore(numero);
in questa maniera è come se avessi detto alla seconda classe "come metodo prendi quello della prima classe ma il suo contenuto deve essere "numero" e non "valore"".
dico bene? è questo il senso del passaggio per valore?
public metodo void (int i){ fai qualcosa}
int j= 10;
nomeOggetto.metodo (j);
è esattamente uguale a
nomeOggetto.metodo (10);
quello che poi con il valore attribuito ad i dipende dal corpo del motodo.
nuovoUtente86
26-04-2010, 11:57
solo ed esclusivamente in presenza di tipi primitivi (ed in realtà con gli oggetti immutabili come le stringhe).
nuovoUtente86
26-04-2010, 12:08
Si. Le stringhe persò essendo oggetti vengono trattati come tali, anche se alla fine la gestione è per valore, per via della loro natura immutabile.
khelidan1980
04-05-2010, 15:54
In realtà in java il passaggio è per valore per i tipi primitivi, mentre è per "copia di reference" per i tipi oggetto.
mah diciamo che la copia del reference io la considero un passaggio per valore, sono per quella scuola di pensiero
nuovoUtente86
04-05-2010, 16:10
mah diciamo che la copia del reference io la considero un passaggio per valore, sono per quella scuola di pensiero
E' parificabile ad un passaggio per valore, solo in presenza di oggetti immutabili come le stringhe. Qualora ci sia anche un solo metodo mutatore (o una variabile con scope valido) non è assolutamente un passaggio per valore, che implica il mancato effetto, sull' entità originale, di eventuali modifiche.
banryu79
04-05-2010, 17:11
[...]
non è assolutamente un passaggio per valore, che implica il mancato effetto, sull' entità originale, di eventuali modifiche.
Mah, dipende.
Una reference ad un oggetto viene passata come parametro ad un metodo.
La reference sta da qualche parte in memoria: viene letto il suo contenuto e viene copiato in una nuova reference, locale al metodo chiamato.
Io questo l'ho sempre sentito chiamare "copia per valore".
La reference, in Java, non è altro che un puntatore costante (da non confondere con un puntatore a costante), quindi la reference locale, che è copia della reference passata come parametro, non può essere modificata (come indirizzo di allocazione, al massimo la si può far puntare ad un altro oggetto).
Risultato? La reference esterna non la puoi modificare, il che combacia con la definizione che hai dato di passagio per valore. Notare che in tutto questo l'oggetto effettivo non entra in gioco: per tutto il tempo lui è rimasto là dov'era al tempo della sua allocazione tramite l'operatore new (al netto di eventuali spostamenti & cazzi e mazzi che può combinare il Garbage Collector, ma non me ne intendo, non so se ci siano implementazioni di GC che deframmentano l'heap :D ).
Attenzione quindi che
A) in Java il passaggio dei parametri ai metodi è sempre e solo per valore;
B) Ciò che viene effettivamente copiato/passato ad un metodo sono i tipi primitivi del linguaggio (boolean, byte, short, int, long, float, double) e le reference a un oggetto, mai gli oggetti veri e propri [e grazie a questo è molto efficiente proprio perchè non si verificano mai operazioni di copia degli oggetti, a differenza ad esempio di C/C++].
nuovoUtente86
04-05-2010, 17:22
Mah, dipende.
Una reference ad un oggetto viene passata come parametro ad un metodo.
La reference sta da qualche parte in memoria: viene letto il suo contenuto e viene copiato in una nuova reference, locale al metodo chiamato.
Io questo l'ho sempre sentito chiamare "copia per valore".
La reference, in Java, non è altro che un puntatore costante (da non confondere con un puntatore a costante), quindi la reference locale, che è copia della reference passata come parametro, non può essere modificata (come indirizzo di allocazione, al massimo la si può far puntare ad un altro oggetto).
Risultato? La reference esterna non la puoi modificare, il che combacia con la definizione che hai dato di passagio per valore. Notare che in tutto questo l'oggetto effettivo non entra in gioco: per tutto il tempo lui è rimasto là dov'era al tempo della sua allocazione tramite l'operatore new (al netto di eventuali spostamenti & cazzi e mazzi che può combinare il Garbage Collector, ma non me ne intendo, non so se ci siano implementazioni di GC che deframmentano l'heap :D ).
Attenzione quindi che
A) in Java il passaggio dei parametri ai metodi è sempre e solo per valore;
B) Ciò che viene effettivamente copiato/passato ad un metodo sono i tipi primitivi del linguaggio (boolean, byte, short, int, long, float, double) e le reference a un oggetto, mai gli oggetti veri e propri [e grazie a questo è molto efficiente proprio perchè non si verificano mai operazioni di copia degli oggetti, a differenza ad esempio di C/C++].
Eventuali modifiche effettuate attraverso (e non al) il riferimento passato (per copia) alla funziona, hanno effetto sull' oggetto puntato? Se la risposta è si allora non c'è passaggio per valore.
Cosa differenzia questo meccanismo da quello del C/C++, il fatto che al posto di passare il puntatore tale e quale(detto in maniera molto poco formale), si va a leggere l' indirizzo contenuto nella variabile reference e se ne fa una copia, ma ciò non esula dal fatto che ci sia un accesso diretto all' oggetto in questione.
Eventuali modifiche effettuate attraverso (e non al) il riferimento passato (per copia) alla funziona, hanno effetto sull' oggetto puntato? Se la risposta è si allora non c'è passaggio per valore.
Cosa differenzia questo meccanismo da quello del C/C++, il fatto che al posto di passare il puntatore tale e quale(detto in maniera molto poco formale), si va a leggere l' indirizzo contenuto nella variabile reference e se ne fa una copia, ma ciò non esula dal fatto che ci sia un accesso diretto all' oggetto in questione.
Scusa, ma non capisco: la tua definizione di passaggio per valore mi sembra troppo restrittiva: sembrerebbe che gli uniche variabili passabili "per valore" siano quelli "primitivi". In ogni caso, per passare un oggetto bisogna per forza o farne una copia, o passare un riferimento (puntatore) ad esso. In una variabile parametro che è... una copia di quella originale. Col passaggio per riferimento del C, invece, si realizza un ulteriore livello di indirezione, passando un riferimento... al riferimento. Cosa che naturalmente è possibile fare anche in un programma Java, ma non è supportata direttamente dal linguaggio.
Ammetto però che la mia conoscenza del C / C++ è molto meno approfondita di quella del Java, per cui potrei avere frainteso qualche definizione.
nuovoUtente86
04-05-2010, 19:13
sembrerebbe che gli uniche variabili passabili "per valore" siano quelli "primitivi".
è cosi: il passaggio per copia presuppone una surroga del valore memorizzato. Copia che nel caso degli oggetti, in Java, viene operata a carico del reference e non dell' entità (che viene trattato come un tipo primitivo), ovvero si copia l' indirizzo cui l' oggetto si trova sull' heap. Tale meccanismo non può essere considerato per copia (non viene clonato, quindi reso immune alle modifiche, in maniera profonda alcun oggetto) ne per riferimento, inteso alla C, perchè non è possibile effettuare la classica funzione di swap senza ricorrere all' espediente dei vettori unitari. Quello che Java utilizza ha un nome preciso ovvero " copy of the reference ".
... ne per riferimento, inteso alla C, perchè non è possibile effettuare la classica funzione di swap senza ricorrere all' espediente dei vettori unitari...
Ma questo è dovuto al fatto che l'operatore '=' in java non clona gli oggetti come in C++, ma opera sui riferimenti.
O no?
Java ha il passaggio per valore e stop, esattamente come C.
Dire il contrario significa non aver chiaro il concetto di variabile e di valore.
Se ho una variabile x e un metodo m che accetta un argomento p, quando dico:
m(x)
p cos'è?
Se è una variabile il cui valore è lo stesso di x è passaggio per valore.
Se è una variabile il cui valore è l'indirizzo di x è passaggio per riferimento.
La dereferenziazione cui eventualmente posso sottoporre il parametro non c'entra una mazza coi termini del passaggio della variabile: è un'altra operazione.
Sarebbe come dire che l'invocazione di metodo in Java supporta la cancellazione del disco fisso perchè dentro a quel metodo posso scrivere "format c:".
nuovoUtente86
04-05-2010, 20:29
Java ha il passaggio per valore e stop, esattamente come C.
Dire il contrario significa non aver chiaro il concetto di variabile e di valore.
Se ho una variabile x e un metodo m che accetta un argomento p, quando dico:
m(x)
p cos'è?
Se è una variabile il cui valore è lo stesso di x è passaggio per valore.
Se è una variabile il cui valore è l'indirizzo di x è passaggio per riferimento.
La dereferenziazione cui eventualmente posso sottoporre il parametro non c'entra una mazza coi termini del passaggio della variabile: è un'altra operazione.
Sarebbe come dire che l'invocazione di metodo in Java supporta la cancellazione del disco fisso perchè dentro a quel metodo posso scrivere "format c:".
Il fulcro della questione è più filosofico che pratico.
In Java esiste un passaggio per riferimento. No almeno io non l' ho mai detto.
Java passa i parametri per copia? Si anche questo è vero, ma dire che il passaggio sia sempre e solo per copia è quantomeno riduttivo o può generare confusione.
Object o=new Object()
la variabile o contiene un riferimento alla locazione contenete l' oggetto
faiQualcosa (Object o){}
faiQualcosa(o);
riceve una copia dell' indirizzo dove si trova l' Object, attraverso cui potervi accedere.
E' corretto dire che le variabili siano passate per valore? Si per parliamo di variabili, ma non se parliamo di Oggetti in sè. Mentre in c++ è possibile passare una copia dell' oggetto, in Java ciò non è possibile in quanto ad essere copiato è il riferimento che, come già detto, è trattato come qualsiasi altro tipo primitivo.
Nono, il fulcro non è filosofico.
Nel passaggio si parla di passaggio di variabili, non altro. Quando in C++ passi una variabile ad un metodo il cui parametro è "by reference" sempre la variabile passi:
int x = 10;
void fun(int& p) { p = 20; }
fun(x) <- x viene passato alla funzione
Hai una variabile che viene passata ad una funzione esattamente come fai in Java a prescidere dal genus di quella variabile.
Non è che non si possano esplorare nuove qualificazione, ci mancherebbe. Ma il problema di dire "ok, lo chiamiamo passaggio per copia di riferimento" è che la differenza che sta tra il passaggio per copia di riferimento e "il passaggio per copia di primitivo" è la stessa che c'è tra il riferimento e il primitivo: uno è dereferenziabile, l'altro no.
nuovoUtente86
04-05-2010, 21:23
Con il filosofico non mi riferivo alla differenza valore, riferimento (ci mancherebbe) ma alle mie considerazioni a riguardo delle nomenclatura nei post precedenti.
All' atto pratico l' importante è comprendere che, in java, le istanze vengono puntate attraverso variabili reference, e queste vengono copia al momento del passaggio, per cui eventuali modifiche allo stato dell' oggetto hanno effetto, mentre eventuali assegnamenti hanno solo scope locale alla funzione.
^TiGeRShArK^
04-05-2010, 23:34
Eventuali modifiche effettuate attraverso (e non al) il riferimento passato (per copia) alla funziona, hanno effetto sull' oggetto puntato? Se la risposta è si allora non c'è passaggio per valore.
Cosa differenzia questo meccanismo da quello del C/C++, il fatto che al posto di passare il puntatore tale e quale(detto in maniera molto poco formale), si va a leggere l' indirizzo contenuto nella variabile reference e se ne fa una copia, ma ciò non esula dal fatto che ci sia un accesso diretto all' oggetto in questione.
è un passaggio per valore di tutti i tipi primitivi. Non esiste in alcun modo il passaggio per riferimento. Tra i tipi primitivi in java rientrano i reference.
In sintesi funziona tutto semplicemente così senza tirare in ballo passaggi per riferimento che NON esistono in java.
^TiGeRShArK^
04-05-2010, 23:36
è cosi: il passaggio per copia presuppone una surroga del valore memorizzato. Copia che nel caso degli oggetti, in Java, viene operata a carico del reference e non dell' entità (che viene trattato come un tipo primitivo), ovvero si copia l' indirizzo cui l' oggetto si trova sull' heap. Tale meccanismo non può essere considerato per copia (non viene clonato, quindi reso immune alle modifiche, in maniera profonda alcun oggetto) ne per riferimento, inteso alla C, perchè non è possibile effettuare la classica funzione di swap senza ricorrere all' espediente dei vettori unitari. Quello che Java utilizza ha un nome preciso ovvero " copy of the reference ".
No, è sempre un passaggio per copia del valore.
Solo che se il valore passato del tipo primitivo è un riferimento si ha il passaggio per copia del riferimento che non è altro che un caso specifico dell'unico metodo esistente di passaggio dei parametri in java: il passaggio per copia del valore.
^TiGeRShArK^
04-05-2010, 23:38
Il fulcro della questione è più filosofico che pratico.
In Java esiste un passaggio per riferimento. No almeno io non l' ho mai detto.
Java passa i parametri per copia? Si anche questo è vero, ma dire che il passaggio sia sempre e solo per copia è quantomeno riduttivo o può generare confusione.
Object o=new Object()
la variabile o contiene un riferimento alla locazione contenete l' oggetto
faiQualcosa (Object o){}
faiQualcosa(o);
riceve una copia dell' indirizzo dove si trova l' Object, attraverso cui potervi accedere.
E' corretto dire che le variabili siano passate per valore? Si per parliamo di variabili, ma non se parliamo di Oggetti in sè. Mentre in c++ è possibile passare una copia dell' oggetto, in Java ciò non è possibile in quanto ad essere copiato è il riferimento che, come già detto, è trattato come qualsiasi altro tipo primitivo.
No, non è assolutamente riduttivo.
Funziona ESATTAMENTE così.
Java passa per copia solo il valore dei tipi primitivi.
Che poi esista un tipo primitivo di tipo reference è assolutamente ininfluente, il passaggio resta sempre per copia del valore.
nuovoUtente86
05-05-2010, 00:11
Mai parlato di passaggio per riferimento, ma di copia del riferimento (trattato esattamente come gli altri primitivi) che è esattamento ciò che java fa.
Inoltre ho posto l' attenzione dalla prospettiva oggetto in se, rappresentato dalla variabile reference.per cui essendo vero che le variabili vengono passate per copia, un oggetto viene passato (vedendolo in maniera astratta, perchè java non ha, di fatto, variabili che contengono oggetti)copiandone il suo riferimento.
Sia chiaro, siamo concordi sul modo in cui avviene il passaggio (del resto è una specifica), ma dal punto di visto della terminologia ho presentato la mia idea, condivisibile o meno.
^TiGeRShArK^
05-05-2010, 08:16
Mai parlato di passaggio per riferimento, ma di copia del riferimento (trattato esattamente come gli altri primitivi) che è esattamento ciò che java fa.
Inoltre ho posto l' attenzione dalla prospettiva oggetto in se, rappresentato dalla variabile reference.per cui essendo vero che le variabili vengono passate per copia, un oggetto viene passato (vedendolo in maniera astratta, perchè java non ha, di fatto, variabili che contengono oggetti)copiandone il suo riferimento.
Sia chiaro, siamo concordi sul modo in cui avviene il passaggio (del resto è una specifica), ma dal punto di visto della terminologia ho presentato la mia idea, condivisibile o meno.
Ma non può essere condivisibile perchè è sbagliata.
Le specifiche del linguaggio Java 3° edizione dicono questo:
4. Method parameters (§8.4.1) name argument values passed to a method. For every parameter declared in a method declaration, a new parameter variable is created each time that method is invoked (§15.12). The new variable is initial- ized with the corresponding argument value from the method invocation. The method parameter effectively ceases to exist when the execution of the body of the method is complete.
Quindi java, secondo le specifiche del linguaggio, utilizza sempre il passaggio per copia del valore.
nuovoUtente86
05-05-2010, 10:40
Ma non può essere condivisibile perchè è sbagliata.
Le specifiche del linguaggio Java 3° edizione dicono questo:
Quindi java, secondo le specifiche del linguaggio, utilizza sempre il passaggio per copia del valore.
Sbagliata secondo cosa?
Java manipola gli oggetti attraverso riferimenti, tali riferimenti vengono passati per copia (o per valore). Cosa ci sarebbe di sbagliato?
Anche perchè affermare che sia sbagliato, presuppone che la "copia del reference" abbia un significato differente.
banryu79
05-05-2010, 11:00
Sbagliata secondo cosa?
Java manipola gli oggetti attraverso riferimenti, tali riferimenti vengono passati per copia (o per valore). Cosa ci sarebbe di sbagliato?
Anche perchè affermare che sia sbagliato, presuppone che la "copia del reference" abbia un significato differente.
PGI ti aveva già risposto in maniera sintetica e precisa, con questo:
Java ha il passaggio per valore e stop, esattamente come C.
Dire il contrario significa non aver chiaro il concetto di variabile e di valore.
Se ho una variabile x e un metodo m che accetta un argomento p, quando dico:
m(x)
p cos'è?
Se è una variabile il cui valore è lo stesso di x è passaggio per valore.
Se è una variabile il cui valore è l'indirizzo di x è passaggio per riferimento.
(era quello che cercavo di dire io ieri sera, poi mi era venuto in mente di farti l'esempio di una funzione C il cui parametro formale è un puntatore mentre invece il parametro reale, al momento della chiamata, è una variabile da cui si estrae l'indirizzo tramite l'operatore &, ma era ora di staccare dal lavoro e non avevo voglia di scrivere il post).
nuovoUtente86
05-05-2010, 11:46
PGI ti aveva già risposto in maniera sintetica e precisa, con questo:
(era quello che cercavo di dire io ieri sera, poi mi era venuto in mente di farti l'esempio di una funzione C il cui parametro formale è un puntatore mentre invece il parametro reale, al momento della chiamata, è una variabile da cui si estrae l'indirizzo tramite l'operatore &, ma era ora di staccare dal lavoro e non avevo voglia di scrivere il post).
Continuiamo a non capirci: sono perfettamente d' accordo con te sul fatto che in C/C++ nel caso di utilizzo dei puntatori e dell' operatore di "address-of" (diverso il discorso del tipo "reference") ricadiamo nel medesimo caso di Java ovvero di copiare il contenuto della variabile, che di fatto è un indirizzo: del resto la logica di funzionamento, a meno dell' aritmetica a favore dei puntatori, è la stessa.
Quello che voglio sottolineare è che non mi piace etichettare come,"tutto per copia" e bon, non fosse altro perchè ciò può generare confusione in chi si approccia al linguaggio
banryu79
05-05-2010, 13:33
Quello che voglio sottolineare è che non mi piace etichettare come,"tutto per copia" e bon, non fosse altro perchè ciò può generare confusione in chi si approccia al linguaggio
E' questo il punto: a te non piacerà etichettare con un "tutto per copia", ma di fatto è quello che succede. Quindi è corretto dirlo chiaramente soprattutto a beneficio del neofita.
Poi gli si lascia capire, oppure gli si spiega esplicitamente, che in Java le istanze degli oggetti non sono passate; mai.
Ciò che viene passata è la copia del riferimento all'oggetto, la reference.
Credo che per un neofita la cosa che può generare qualche incertezza/incomprensione, se non ben spiegata (specie se il neofita è tale non solo esclusivamente dal punto di vista del linguaggio) è abituarsi a leggere questa sintassi:
Object o = new Object();
e considerare la variabile 'o' come "l'oggetto", senza altre distinzioni.
E' neccesario per il neofita capire che ciò che sta a sinistra dell'operatore '=' non è "l'oggetto" ma il "riferimento all'oggetto" (Java reference) e ciò che sta a destra dell'operatore '=', in particolare il prodotto dell'operatore 'new', è "l'stanza dell'oggetto".
E che è la reference che viene passata ai metodi, e viene passata per copia.
Poi ci sono i tipi primitivi, e dato che non possono essere indirettamente referenziati (proprio perchè in Java non esistono i pointer, ne pointer operators e neanche pointer arithmetic) possono essere passati solo per copia.
Risultato: in Java gli argomenti dei metodi invocati sono sempre e solo passati per copia.
Ripeto il punto che sintetizza al massimo la questione:
Se ho una variabile x e un metodo m che accetta un argomento p, quando dico:
m(x)
p cos'è?
Se è una variabile il cui valore è lo stesso di x è passaggio per valore.
Se è una variabile il cui valore è l'indirizzo di x è passaggio per riferimento.
Questo è quello che, a mio avviso, bisognerebbe dire ai neofiti, per non causare confusione, circa il passaggio degli argomenti ai metodi.
nuovoUtente86
05-05-2010, 14:11
credo sia, già, stato postato un link esterno all' inizio di questa discussione ad un interessante trafiletto di J. Gosling che esplicita bene la questione.
Some people will say incorrectly that objects are passed “by reference.” In programming language design, the term pass by reference properly means that when an argument is passed to a function, the invoked function gets a reference to the original value, not a copy of its value. If the function modifies its parameter, the value in the calling code will be changed because the argument and parameter use the same slot in memory…. The Java programming language does not pass objects by reference; it passes object references by value. Because two copies of the same reference refer to the same actual object, changes made through one reference variable are visible through the other. There is exactly one parameter passing mode — pass by value — and that helps keep things simple.
credo sia, già, stato postato un link esterno all' inizio di questa discussione ad un interessante trafiletto di J. Gosling che esplicita bene la questione.
Sì
Some people will say incorrectly that objects are passed “by reference.” In programming language design, the term pass by reference properly means that when an argument is passed to a function, the invoked function gets a reference to the original value, not a copy of its value. If the function modifies its parameter, the value in the calling code will be changed because the argument and parameter use the same slot in memory…. The Java programming language does not pass objects by reference; it passes object references by value. Because two copies of the same reference refer to the same actual object, changes made through one reference variable are visible through the other. There is exactly one parameter passing mode — pass by value — and that helps keep things simple.
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.