Visualizzazione dei risultati da 1 a 9 su 9
  1. #1

    [JAVA] Dog d = new Dog() crea due oggetti?

    Salve,

    partendo da alcune considerazioni teoriche lette sui manuali e di un passo di questo forum vorrei fare alcune considerazioni riguardo l'istruzione nel titolo, ed i puntatori in generale, e proporvele al fine di essere smentito se le mie "intuizioni" risultassero erronee. Penso che questa discussione possa essere di aiuto a molti di quelli che si avvicinano a Java e non solo.

    Nella seguente istruzione:
    Codice PHP:
    Dog d = new Dog(); 
    Abbiamo un istruzione di assegnazione. L'operatore binario uguale (=) è un operatore di assegnazione che associa da dx a sx. Quindi viene valutata per prima l'espressione
    1) new Dog();
    L'operatore new alloca la memoria in cui verrà conservato l'oggetto Dog, dopodiché new chiama il costruttore Dog() per inizializzare le variabili d'istanza del nuovo oggetto Dog in uno stato consistente.
    L'istruzione new Dog(), quindi, serve a creare un nuovo oggetto anonimo di tipo Dog. Gli oggetti anonimi, privi cioè di riferimenti espliciti con cui chiamarli, vengono usati anche nelle chiamate di metodo a cascata. In realtà, suppongo, al nuovo oggetto Dog Java assegnerà cmq un riferimento automatico per i suoi fini interni, a noi però sconosciuto.
    2) Dog d
    Questa istruzione crea un oggetto d di tipo Dog, a partire cioè dalla classe Dog. Questo oggetto però non è stato inizializzato, quindi le sue variabili d'istanza si trovano in uno stato inconsistente. Il valore di d è quindi null e pertanto inutilizzabile.
    3) Operatore uguale (=)
    L'operatore di assegnazione assegna il valore dell'oggetto anonimo new Dog() all'oggetto d di tipo Dog

    Nell'istruzione Dog d = new Dog() vengono quindi creati 2 oggetti : uno anonimo privo di riferimento ed uno non inizializzato il quale, per mezzo dell'operatore uguale, sarà inizializzato con i valori dell'oggetto anonimo.

    Ad ogni oggetto è associato un indirizzo di memoria, grazie al quale è possibile reperire l'esatta posizione in cui si trova l'oggetto all'interno della memoria temporanea dell'elaboratore, al fine di poterlo usare. Quindi in realtà essendoci due oggetti inizialmente ci sono due corrispondenti indirizzi di memoria che grazie all'operatore di assegnamento vengono in qualche modo associati.

    Il problema nasce dalle diverse diciture adottate dai vari manuali. Nei vari manuali ci si riferisce a d sia come "oggetto" che come "variabile reference". Probabilmente entrambe le diciture sono corrette...ma non sarebbe più corretto dire, se le mie considerazioni sono giuste, che d è un oggetto con un suo specifico indirizzo di memoria a cui viene passato il valore di un oggetto dello stesso tipo ma omonimo?
    La differenza è sottile e ve la espongo con altri termini:
    E' l'indirizzo di memoria di d che viene cambiato, passando dall'iniziale indirizzo assegnatogli a quello dell'oggetto anonimo o in realtà i due indirizzi rimangono immutati, solo che ora d contiene i valori dell'oggetto anonimo e quindi usare d o l'oggetto anonimo - nella pratica - risulta indifferente?

    Infine, la creazione di due oggetti per usarne, nella pratica, solo uno non è uno spreco notevole di risorse?

    Grazie dell'attenzione, attendo correzioni
    Matteo

  2. #2
    Ciao,
    solo con l'istruzione 'new' crei una istanza di una classe,
    ovvero un oggetto che risiede in memoria.

    la dichiarazione 'Dog d' non occupa indirizzi di memoria perchè non è un oggetto.

    Dog d = new Dog() crea un oggetto che è referenziato dalla variabile d:
    d è l'indirizzo di memoria dove risiede l'oggetto Dog.

    Ciao
    Mirko Agrati
    WEB : http://mirkoagrati.110mb.com
    RSS : http://feeds.feedburner.com/MirkoAgratiArticoli

  3. #3
    Ciao,
    anzitutto grazie della risposta.

    Quindi, sebbene spesso leggo scritto che d è un oggetto di tipo Dog, sarebbe più corretto dire che d è una variabile di riferimento atta a contenere un indirizzo di memoria di un oggetto di tipo Dog (o sottoclassi), che nella fattispecie è new Dog()?
    In altre parole mentre new Dog() crea fisicamente un oggetto di tipo Dog senza assegnazione esplicita di un indirizzo di memoria associato per poterlo poi recuperare, d non è altro che una variabile che contiene l'indirizzo di memoria nel quale risiede l'oggetto anonimo assegnato per mezzo dell'operatore di assegnamento?
    Riepilogando:
    [list=1][*]d è una variabile reference[*]new Dog() è l'oggetto di tipo Dog[/list=1]

    Dire quindi che d è un oggetto di tipo Dog è solo una estensione imprecisa del concetto di variabile reference?

    ...qualcosa non mi quadra

  4. #4
    con la parola chiave new istanzi formalmente un oggetto. Basterebbe l'istruzione

    codice:
    new Classe();
    per istanziare l'oggetto. Ma così facendo l'oggetto appena creato non avrebbe un "nome" (o più tecnicamente reference ) e quindi non sarebbe utilizzabile.

    Con l'assegnazione

    codice:
    Classe o = new Classe();
    non si sta utilizzando una "variabile tradizionale" (come sarebbe nel caso di int, double, ecc..) bensì di una variabile che alcuni definiscono "puntatore" (il concetto di puntatore in realtà è differente e non esiste in Java). Un puntatore può essere definito a grandi linee come una variabile che contiene un indirizzo di memoria.
    C'è una sostanziale differenza tra il dichiarare variabili di tipo primitivo (int, double,...) e di tipo non primitivo (reference). Ad esempio, con questa situazione:

    codice:
    double unNumero = 1.0;
    Date unaData = new Date();
    
    public class Data {
       public int giorno;
       public int mese;
       public int anno;
    }
    si avrebbe una situazione in memoria del tipo:

    codice:
              ___
    unNumero |1.0|
                   
    
             __________
    unaData |0XABCD2346| --->    __
                                |       oggetto di tipo Data
                                |
                                |      giorno = 0
                                |      mese = 0
                                |      anno = 0
                                |__
    Al mio segnale... scatenate l'inferno!

  5. #5
    Dunque,
    d è il puntatore all'oggetto new Dog(), che risiede in memoria,
    tramite il quale è possibile referenziare tale oggetto.

    Senza assegnare l'indirizzo di new Dog() a d,
    potresti utilizzare l'oggetto solo in forma anonima,
    cioè una sola volta:

    int zampe = new Dog().getZampeNumber();

    tramite d, invece, puoi continuare a referenziarlo:

    int zampe = d.getZampeNumber();
    String razza = d.getRazza();
    ecc....

    Non capisco cosa non ti è chiaro.
    Nei post precedenti hai menzionato il termine "puntatore",
    quindi ne conosci il significato.
    E' lo stesso concetto dei puntatori di C e C++,
    solo che a differenza dei suddetti linguaggi,
    dove puoi anche non 'puntare' un indirizzo di memoria
    Java ha solo reference.

    Ciao
    Mirko Agrati
    WEB : http://mirkoagrati.110mb.com
    RSS : http://feeds.feedburner.com/MirkoAgratiArticoli

  6. #6
    I miei dubbi sono sorti dopo aver letto questa frase postata dall'ultente andbin nel precedente post da me aperto [JAVA] le String sono immutabili?
    Per la precisione:

    mattew80
    String s = new String("Hello");

    Esiste anche una variante sintetica per la creazione di un oggetto String, che è la seguente:

    String s = "Hello";

    andbin
    C'è una differenza sostanziale: nel primo caso ci sono 2 oggetti, nel secondo solo 1.
    Le stringhe "literal" (letterali) vengono messe in un "constant pool". Nel primo caso passi una stringa literal al costruttore di String e poi viene creato un nuovo String con lo stesso contenuto della stringa literal.
    Come vedi andbin precisava che con l'istruzione
    String s = new String("Hello");
    venivano creati due oggetti e non uno! Questo mi ha fatto ripensare al modo in cui ho sempre inteso il concetto di reference in java e da qui l'esistenza del post per poterne discutere. Sarebbe interessante se anche andbin potesse partecipare alla discussione.

  7. #7
    Utente di HTML.it L'avatar di Stoicenko
    Registrato dal
    Feb 2004
    Messaggi
    2,254
    Questo ti fa capire che non tutti hanno ben in mente il concetto di Oggetto e Riferimento ad un oggetto..

    Nel tuo caso dire "d è un oggetto di tipo dog" è un volgarismo comune e deve essere tradotto in "d è un reference ad un oggetto di tipo dog allocato in memoria"...

    Per chi mastica java da molto la cosa non ha più importanza (quello che dice non tradisce ciò che pensa) ma per i neofiti sarebbe meglio che si correggessero..

    Non per nulla all'università prima di fare cose complicate in c++ si fa "aritmetica dei puntatori".. In java no perchè i puntatori non esistono.. (ci crediamo?)..

    Bye

  8. #8
    Ok, grazie a tutti.
    Quindi il dubbio che mi era venuto in seguito a quel post è svanito

    Nell'istruzione

    Dog d = new Dog();
    d è una variabile reference nella quale è racchiuso l'indirizzo di memoria assegnatogli dall'operatore di assegnamento, in seguito alla creazione di un nuovo oggetto Dog() per mezzo dell'operatore new. Viene creato quindi un solo oggetto Dog, come ho sempre saputo del resto.

    Non mi sento di criticare andbin. Probabilmente il suo intervento sulla creazione degli oggetti String, vale effettivamente solo per gli oggetti String, che sono cmq oggetti particolari.
    Cmq nei prossimi giorni dovrò studiare proprio le String, quindi darò un occhiata a questi due thread.

    Gutta cavat lapidem
    [La goccia scava la pietra]
    ***
    (Ovidio)

  9. #9
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Gli oggetti String sono particolari, perché è possibile scrivere una stringa come "literal" nel sorgente. La domanda che ci si può porre è: se scrivo una stringa "hello" in un sorgente, che cosa è e dove viene messa??

    Le stringhe literal vengono messe dal compilatore in una area di memoria speciale chiamata "String constant pool" o più semplicemente "constant pool". Ogni stringa literal è a tutti gli effetti un oggetto di classe String, trattata solo in maniera particolare.

    Veniamo a degli esempi che possono chiarire la questione.

    String s1 = "hello";
    String s2 = "hello";
    System.out.println (s1 == s2); // stampa "true"

    In questo caso nel constant pool c'è 1 solo oggetto "hello", il compilatore si accorge che sono la stessa stringa e mette nel pool 1 solo oggetto. I due reference sono quindi esattamente uguali e pertanto una comparazione dei reference dà come risultato true.

    Altro esempio:

    String s1 = new String ("hello");
    String s2 = new String ("hello");
    System.out.println (s1 == s2); // stampa "false"

    In questo caso quando si raggiunge la terza linea, gli oggetti in ballo sono ben 3. L'oggetto "hello" della stringa literal (nel constant pool) e 2 oggetti String allocati sul "heap" a runtime e che hanno lo stesso contenuto (come sequenza di caratteri) della stringa literal.
    I reference s1 e s2 sono diversi, perché gli oggetti sono stati istanziati con new e pertanto sull'heap ci sono 2 oggetti String ben distinti.

    Questa è la realtà delle cose nella gestione delle stringhe in Java.


    EDIT: per tornare alla questione iniziale del thread "Dog d = new Dog() crea due oggetti?" la risposta semplicemente è -no-. Con new si istanzia sempre e solo 1 oggetto.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.