|
Wiki
UniCrema
Materie per semestre
Materie per anno
Materie per laurea
Help
|
|
Uni.TettyJAVA History
Hide minor edits - Show changes to output
Deleted lines 4-7:
(:include Servizi.DaModificare:)
->[[!'''DaModificare''']]: ''bisogna sottolineare in rosso le risposte alle domande''.
Changed lines 6-7 from:
:include Servizi.DaModificare:)
to:
(:include Servizi.DaModificare:)
Changed lines 5-9 from:
%warning%'''Warning!'''\\ Si cerca qualche anima pia che sottolinei in rosso le risposte alle domande,\\ e magari alla fine metta anche la lista delle domande collegate al capitolo.\\\ Per questo motivo la pagina appartiene alla categoria [[!DaModificare]]
to:
:include Servizi.DaModificare:)
->[[!'''DaModificare''']]: ''bisogna sottolineare in rosso le risposte alle domande''.
Changed lines 523-525 from:
[[Torna alla pagina di Programmazione degli Elaboratori -> Uni.ProgrammazioneElaboratori]] ---- [[!UniCrema]]
to:
[[Torna alla pagina di Programmazione degli Elaboratori -> Uni.ProgrammazioneElaboratori]]
Changed line 3 from:
[[Torna alla pagina di Tetty -> Tetty]]
to:
[[Torna alla pagina di Programmazione degli Elaboratori -> Uni.ProgrammazioneElaboratori]]
Changed line 523 from:
[[Torna alla pagina di Tetty -> Tetty]]
to:
[[Torna alla pagina di Programmazione degli Elaboratori -> Uni.ProgrammazioneElaboratori]]
Changed lines 124-125 from:
<modificatore> class <nome classe> extends <super classe> implements <interfaccia1> ... <interfaccia2>
to:
<modificatore> class <nome classe> extends <super classe> implements <interfaccia1> ... <interfaccia2>
Changed lines 6-7 from:
Si cerca qualche anima pia che sottolinei in rosso le risposte alle domande, e magari alla fine metta anche la lista delle domande collegate al capitolo.\\\
to:
Si cerca qualche anima pia che sottolinei in rosso le risposte alle domande,\\ e magari alla fine metta anche la lista delle domande collegate al capitolo.\\\
Deleted line 2:
%center bgcolor=red border='3px dotted yellow' padding=3px define=warning%
Added lines 10-11:
%titolo%''':: Integrazione su JAVA ::'''
Changed lines 520-522 from:
[[Torna alla pagina di Tetty -> Tetty]]
to:
[[Torna alla pagina di Tetty -> Tetty]] ---- [[!UniCrema]]
Added line 2:
Changed line 7 from:
Si cerca qualche anima pia che metta un sommario a questa pagina, e sottolinei in rosso le risposte alle domande, e magari alla fine metta anche la lista delle domande collegate al capitolo.\\\
to:
Si cerca qualche anima pia che sottolinei in rosso le risposte alle domande, e magari alla fine metta anche la lista delle domande collegate al capitolo.\\\
Added lines 11-31:
!!!!Indice *[[JAVA -> #java]] *[[Il Riferimento e gli Object -> #riferimenti]] *[[La classe String -> #string]] *[[Come faccio a dichiarare un riferimento? -> #dichiarareriferimento]] *[[Creare vettori -> #crearevettori]] *[[Dichiarazione di una classe -> #dichiarazioneclasse]] *[[Metodi, Costruttori e Attributi -> #mca]] *[[Interfacce -> #interfacce]] *[[Extends e Implements -> #extends]] *[[Interfacce e incapsulamento: modificatori -> #modificatori]] *[[Ereditarietà e Polimorfismo -> #eredita]] *[[Algebra dei tipi -> #algebra]] *[[Polimorfismo -> #polimorfismo]] *[[Errori ed Eccezioni -> #eccezioni]] *[[La via OOP alla gestione di Errori ed Eccezioni -> #viaoop]] *[[I/O in JAVA -> #io]] *[[Serializzazione -> #serializzazione]] ----
[[#java]]
Changed lines 41-42 from:
Ma il vantaggio principale è che, essendo separata dall'hardware, la JavaVM mi permette di giocare finché voglio con memoria e cose simili, che tanto non potrò mai produrre danni perché proprio la JavaVM mi protegge dal fare casini a basso livello, cosa purtroppo simpaticamente possibile col C.
to:
Ma il vantaggio principale è che, essendo separata dall'hardware, la JavaVM mi permette di giocare finché voglio con memoria e cose simili, che tanto non potrò mai produrre danni perché proprio la JavaVM mi protegge dal fare casini a basso livello, cosa purtroppo simpaticamente possibile col C.\\\
[[Torna su -> #su]]
[[#riferimenti]]
Changed lines 61-62 from:
Non è più possibile in Java prendere un riferimento e farlo puntare ad un indirizzo, perché si tratta di una cosa rischiosa. Infatti posso prendere un puntatore e dirgli di puntare a un indirizzo a caso, e mandare tutto il programma in SegFault, e nessuno me lo impedirebbe, e soprattutto è uno di quei bug che non si trovano mai.
to:
Non è più possibile in Java prendere un riferimento e farlo puntare ad un indirizzo, perché si tratta di una cosa rischiosa. Infatti posso prendere un puntatore e dirgli di puntare a un indirizzo a caso, e mandare tutto il programma in SegFault, e nessuno me lo impedirebbe, e soprattutto è uno di quei bug che non si trovano mai.\\\
[[Torna su -> #su]]
[[#string]]
Changed lines 76-77 from:
Il problema dell'Unicode è che descrive ''in astratto'' il sistema delle tabelle, ma non dice niente sulla sua implementazione. Ecco perché sono nate le codifiche UTF: uno standard per implementare la definizione delle tabelle di caratteri inventata da quelli dell'Unicode. Si sa per esempio che in UTF il primo byte mi indica la tabella, il secondo il carattere, e così via. La specifica Unicode di per sé diceva solo: occorre indicare in modo diverso la tabella e il carattere, ma non diceva affatto come.
to:
Il problema dell'Unicode è che descrive ''in astratto'' il sistema delle tabelle, ma non dice niente sulla sua implementazione. Ecco perché sono nate le codifiche UTF: uno standard per implementare la definizione delle tabelle di caratteri inventata da quelli dell'Unicode. Si sa per esempio che in UTF il primo byte mi indica la tabella, il secondo il carattere, e così via. La specifica Unicode di per sé diceva solo: occorre indicare in modo diverso la tabella e il carattere, ma non diceva affatto come.\\\
[[Torna su -> #su]]
[[#dichiarareriferimento]]
Added lines 104-106:
[[Torna su -> #su]]
[[#crearevettori]]
Changed lines 114-116 from:
Che cos'è questo [@new@]? È una sorta di [@malloc@] ma automatizzato. Ci pensa lui ad allocare la memoria necessaria all'interno della JavaVM, e io non devo preoccuparmene.
to:
Che cos'è questo [@new@]? È una sorta di [@malloc@] ma automatizzato. Ci pensa lui ad allocare la memoria necessaria all'interno della JavaVM, e io non devo preoccuparmene.\\\
[[Torna su -> #su]]
[[#dichiarazioneclasse]]
Added lines 139-141:
[[Torna su -> #su]]
[[#mca]]
Added lines 158-160:
[[Torna su -> #su]]
[[#interfacce]]
Changed lines 190-191 from:
Questi due ultimi punti meritano un paragrafo a sé.
to:
Questi due ultimi punti meritano un paragrafo a sé.\\\
[[Torna su -> #su]]
[[#extends]]
Added lines 221-223:
[[Torna su -> #su]]
[[#modificatori]]
Changed lines 232-233 from:
''Protected'' è una cosa diversa: vuol dire che al di fuori non lo può vedere nessuno, ma i miei eredi sì.
to:
''Protected'' è una cosa diversa: vuol dire che al di fuori non lo può vedere nessuno, ma i miei eredi sì.\\\
[[Torna su -> #su]]
[[#eredita]]
Changed lines 281-282 from:
Come ho detto prima, invece, il ''subclassing'' prende dagli antenati anche il codice effettivamente scritto.
to:
Come ho detto prima, invece, il ''subclassing'' prende dagli antenati anche il codice effettivamente scritto.\\\
[[Torna su -> #su]]
[[#algebra]]
Added lines 327-329:
[[Torna su -> #su]]
[[#polimorfismo]]
Changed lines 383-384 from:
Ecco quindi spiegato come l'ereditarietà porti al polimorfismo.
to:
Ecco quindi spiegato come l'ereditarietà porti al polimorfismo.\\\
[[Torna su -> #su]]
[[#eccezioni]]
Changed lines 423-424 from:
Nel mondo delle interfacce grafiche, invece, dove è l'utente a decidere che cosa far fare all'applicazione, i vari clic del mouse o apertura di menu etc. sono detti eventi. Un errore è semplicemente un altro evento, e sta poi alla routine che gestisce gli eventi arrabattarsi per gestire l'errore. Non faccio esempi che qui si dilungherebbero troppo.
to:
Nel mondo delle interfacce grafiche, invece, dove è l'utente a decidere che cosa far fare all'applicazione, i vari clic del mouse o apertura di menu etc. sono detti eventi. Un errore è semplicemente un altro evento, e sta poi alla routine che gestisce gli eventi arrabattarsi per gestire l'errore. Non faccio esempi che qui si dilungherebbero troppo.\\\
[[Torna su -> #su]]
[[#viaoop]]
Changed lines 476-477 from:
Quando un metodo getta un'eccezione, il metodo si interrompe e ritorna a chi lo ha chiamato. Se questo chiamante non gestisce l'eccezione, si torna a chi ha chiamato il chiamante e così via. Si dice che l'eccezione si ''propaga''. Se nessuno la prende, arriva alla JavaVM e si blocca. Di solito cmq c'è qualcuno che prende l'eccezione.
to:
Quando un metodo getta un'eccezione, il metodo si interrompe e ritorna a chi lo ha chiamato. Se questo chiamante non gestisce l'eccezione, si torna a chi ha chiamato il chiamante e così via. Si dice che l'eccezione si ''propaga''. Se nessuno la prende, arriva alla JavaVM e si blocca. Di solito cmq c'è qualcuno che prende l'eccezione.\\\
[[Torna su -> #su]]
[[#io]]
Changed lines 507-508 from:
E naturalmente ci sono tutte le classi che ereditano da ciò e sono specializzate ad esempio nella lettura di file di [@char@] e così via.
to:
E naturalmente ci sono tutte le classi che ereditano da ciò e sono specializzate ad esempio nella lettura di file di [@char@] e così via.\\\
[[Torna su -> #su]]
[[#serializzazione]]
Changed line 513 from:
È un meccanismo JAVA che mi permette di salvare gli oggetti, anche quelli creati da me, in un certo formato, per poi recuperarli così come sono.\\
to:
È un meccanismo JAVA che mi permette di salvare gli oggetti su disco, in un file, anche quelli creati da me, in un certo formato, per poi recuperarli così come sono.\\
Changed lines 516-518 from:
Se invece voglio essere io a decidere come rappresentare i miei oggetti quando li salvo, devo implementare l'interfaccia '''Externalizable'''.
to:
Se invece voglio essere io a decidere come rappresentare i miei oggetti quando li salvo, devo implementare l'interfaccia '''Externalizable'''.\\\
[[Torna su -> #su]]
Changed line 1 from:
to:
(:title Dispense Tetty - Integrazione JAVA:)
Changed lines 6-7 from:
Si cerca qualche anima pia che metta un sommario a questa pagina, e sottolinei in rosso le risposte alle domande, e magari alla fine metta anche la lista delle domande collegate al capitolo
to:
Si cerca qualche anima pia che metta un sommario a questa pagina, e sottolinei in rosso le risposte alle domande, e magari alla fine metta anche la lista delle domande collegate al capitolo.\\\ Per questo motivo la pagina appartiene alla categoria [[!DaModificare]]
Added line 2:
%center bgcolor=red border='3px dotted yellow' padding=3px define=warning%
Added lines 5-8:
%warning%'''Warning!'''\\ Si cerca qualche anima pia che metta un sommario a questa pagina, e sottolinei in rosso le risposte alle domande, e magari alla fine metta anche la lista delle domande collegate al capitolo
----
Changed lines 72-74 from:
Posso creare array con qualsiasi tipo, comprese classi che creo io.
to:
Posso creare array con qualsiasi tipo, comprese classi che creo io.\\\
Che cos'è questo [@new@]? È una sorta di [@malloc@] ma automatizzato. Ci pensa lui ad allocare la memoria necessaria all'interno della JavaVM, e io non devo preoccuparmene.
Changed lines 89-90 from:
Vediamo in dettaglio che cosa ciò significhi.\\\
to:
Per istanziare una classe, cioè creare un oggetto, uso ancora il [@new@]:
tipoClasse classe = new tipoClasse(parametri del costruttore);
Il [@new@] pensa tutto a lui, alloca la memoria etc, e quando la classe non serve più decide lui come disfarsene. Il bello della JavaVM:)
Vediamo in dettaglio che cosa significano quei vari peciotti.\\\
Changed lines 8-10 from:
Il C++ è un'estensione del C orientata agli oggetti. Presenta tutte le caratteristiche della OOP, anche se le implementa in un modo un po' complicato. La via del C pare essere sempre la più complicata. Rispetto al C++, il JAVA ha delle intuizioni piuttosto carine.
to:
Il C++ è un'estensione del C orientata agli oggetti. Presenta tutte le caratteristiche della OOP, anche se le implementa in un modo un po' complicato. La via del C pare essere sempre la più complicata. Rispetto al C++, il JAVA ha delle intuizioni piuttosto carine.\\\
Il JAVA, almeno quello distribuito dalla SUN, è un linguaggio compilato, ma non in linguaggio macchina. Tra il JAVA e il nostro computer c'è uno strato aggiuntivo, detto JAVA VIRTUAL MACHINE, il quale è una astrazione dell'hardware sottostante (il nostro computer) e allo stesso tempo è un hardware virtuale, una sorta di simulatore LC2. I programmi in JAVA vengono compilati in ''bytecode'', che è il particolare linguaggio macchina della macchina virtuale. La JavaVM quindi legge il bytecode, e lo interpreta al volo.\\\
Questo sistema permette di definire un linguaggio che vada bene su tutti i computer con tutti i processori con i sistemi operativi più disparati, il che è un buon vantaggio. Lo svantaggio è che è lento, rispetto ad un programma compilato come il C o il C++.\\ Ma il vantaggio principale è che, essendo separata dall'hardware, la JavaVM mi permette di giocare finché voglio con memoria e cose simili, che tanto non potrò mai produrre danni perché proprio la JavaVM mi protegge dal fare casini a basso livello, cosa purtroppo simpaticamente possibile col C.
Changed lines 212-214 from:
Come ho detto prima, invece, il ''subclassing'' prende dagli antenati anche il codice effettivamente scritto
[to be continued]
to:
Come ho detto prima, invece, il ''subclassing'' prende dagli antenati anche il codice effettivamente scritto.
!!!!Algebra dei tipi ''Warning: i caratteri strani usati in questa sezione sono proprio strani. Qui sono arrotondati, ma dovete immaginarveli tutti squadrati''\\\
L'Algebra dei Tipi è una particolare Algebra usata per spiegare l'ereditarietà. I compilatori dei linguaggi OOP includono dei sistemi per verificare, in base a quest'Algebra, se le regole dell'ereditarietà sono state rispettate o meno. E valgono anche per le cose banali tipo l'assegnazione di un [@char@] ad un [@int@].\\\
'''T'''\\ T è il tipo Top, quello da cui tutti gli altri tipi derivano.\\\
'''┴'''\\ ┴ è il tipo Assurdo, che cerca di riunire interfacce incompatibili
'''A {+ᑕ+} B'''\\ Vuol dire che il tipo A è sottotipo (estende) il tipo B. Quindi A può avere qualche cosa in più di B.\\\
'''E = A ᑎ B'''\\ Vuol dire che il tipo E è il tipo più generale, cioè quello con meno antenati, che estende sia A che B.\\ ᑎ si chiama '''meet'''.\\\
In base a questa '''E = A ᑌ B'''\\ Vuol dire che E è il primo antenato che trovo, da cui sia A che B derivano.\\ ᑌ si chiama '''join'''.\\\
L'assegnazione
tipoX x; tipoY y; x = y;
è valida se ho '''tipoX {+ᑕ+} tipoY'''.\\\
Lo stesso vale per i metodi
//prototipo: dario (tipoX);
//chiamata: dario(tipoY);
è valida sempre se '''tipoX {+ᑕ+} tipoY'''.\\\
!!!!Polimorfismo Il ''polimorfismo'' è la capacità dello stesso oggetto di apparire in forme diverse in contesti diversi.\\ Posso anche dirla così: capacità di oggetti diversi di apparire nella stessa forma a seconda del contesto.\\\
Nei linguaggi tradizionali non c'è polimorfismo, ma solo ''monomorfismo'': per esempio, una funzione accetta come parametri solo oggetti di un certo tipo. I linguaggi polimorfi accettano invece tutti i tipi che si possono "''trasformare''" in un altro tipo, secondo le regole dell'Algebra dei Tipi spiegata qui sopra.\\\
Ci sono diversi tipi di polimorfismo, secondo la classificazione ''Cardelli-Wegner'': * Universale -> * parametrico -> * per inclusione * Ad Hoc -> * overloading -> * coercion
Il polimorfismo del C è del tipo '''ad hoc'': vuol dire che è limitato a pochi tipi predefiniti, scelti, appunto, ''ad hoc''.\\\
La '''coercion''' si ha quando un tipo viene convertito automaticamente in un altro tipo, secondo certe precise regole di promozione. Si pensi ai [@char@] che vengono convertiti in [@int@] e così via nel C: avviene un [@cast@] automatico, lo fa il linguaggio.\\\
Invece, l' '''overloading''' si ha quando fornisco un operatore con lo ''stesso'' nome, ma che ho definito in più modi, ed ognuno di questi modi prende in argomento un tipo diverso.\\ Ciò vuol dire che posso definire una funzione così:
void moltiplica(int valore); void moltiplica(float valore);
Nei linguaggi che supportano l' ''overloading'', è il compilatore scelto a stabilire quale delle due funzioni utilizzare, a seconda che io chiami [@moltiplica@] passandogli un intero oppure un float.\\\
Il polimorfismo '''universale''' invece si applica a tutti i tipi indifferentemente, seguendo le care regolette dell'Algebra dei Tipi.\\\
Quello '''per inclusione''' è quello della OOP: se implemento un'interfaccia, sono un suo sottotipo; se estendo una classe, sono un suo sottotipo.\\\
Il polimorfismo '''parametrico''' è ben diverso. Vuol dire avere la capacità di stabilire il tipo che una funzione ''ritorna'' in base al tipo ''in ingresso''. Questa funzione la dichiarerei così:
Tipo somma(Tipo A, Tipo B);
ma qui [@Tipo@] ''non è'' un particolare tipo, bensì vuol dire: ''prendi il tipo che ti passano come parametro, ed utilizzalo come tipo per la variabile di ritorno''.\\ Avendo definito così la funzione, posso fare con la stessa funzione queste cose:
int gatto; gatto = somma(23, 45);
float cane; cane = somma(23.5, 45.7);
126 dario = new 126("bg669287"); 126 clara = new 126("cr708982"); 126 risultato; risultato = somma(dario, clara);
Capite? È follia! Eppure si può fare, volendo. Si chiama ''programmazione generica'', o ''template programming''. Il C++ so per certo che implementa queste cose, non che io sappia come farlo. Cmq chi ha usato un po' la STL del C++ ha usato implicitamente template, cioè questo tipo di polimorfismo, perché la STL vuol dire proprio ''Standard Template Library''.\\\
Nota: da qualche parte deve essere specificato ''come'' fare la somma tra due oggetti di tipo 126, e anche se sembra una cosa assurda sommare due 126, al compilatore non gliene frega niente: se definisco l'operatore '+' che prende come parametri due oggetti di tipo 126, a lui va benissimo.\\ A livello ancora più generale, dovrebbe essere possibile definire un'operazione dal nome [@compareTo@], e tutti i tipi che la implementano sono comparabili l'un l'altro. Ciò varia da linguaggio a linguaggio, ma vi assicuro che è cosa fattibile.\\\
Ecco quindi spiegato come l'ereditarietà porti al polimorfismo.
!!!!Errori ed Eccezioni ''Eccezione'' = anomalia recuperabile.\\ ''Errore'' = anomalia irrecuperabile.\\\
Ho un'eccezione quando cerco di aprire un file non esistente: errore qua e là ma posso continuare il programma, magari insultando l'utente
if (Fp1 == NULL) printf("Imbecille! Devi specificare il nome file!\n");
Ho un errore quando invece tutto quanto va a puttane, come per esempio vado a scrivere su una porzione di memoria che dovrei lasciare in pace, e il sistema operativo va in SegFault e tutto s'impalla. Gli errori sono quelli che producono gli Schermi Blu della Morte di Windows, e non c'è altro da fare se non riavviare il computer.\\\
Come fare a gestire le eccezioni? Nel passato si sono usati diversi modi.\\\
Il sistema più scarabottolesco è quello delle TRAP e degli INTERRUPT. Se qualcuno si ricorda il divertimento della LC2, qui ritrova terminologia nota. Per esempio, mi arriva una divisione ma il registro mi contiene tutti 0, e la CPU si lamenta e lancia un'INT. Sta poi a me con una TRAP gestirmi l'INT. Se non avete ancora letto del MIX, la TRAP è una trappola che intercetta vari avvenimenti hardware, in questo esempio una ''Division by Zero''.\\\
Il sistema del C è quello dei valori di ritorno. Se tutto va bene ritorno 0, se no ritorno altri numeri, e sta poi a chi ha chiamato la mia funzione capire che cosa è successo.
#define ERR_FILE_NOT_FOUND 32
if (Fp1 == NULL) { printf("File inesistente\n"); return ERR_FILE_NOT_FOUND; }
Un altro espediente è quello delle variabili di stato, cioè le variabili che vengono dichiarate prima del [@main@], e che quindi sono visibili a tutti. Da ricordare che le variabili globali sono ''il male'' e sono da evitare, perché chiunque le può scrivere a caso e/o a piacimento. Si potrebbero usare così:
int ERRORE = 0,
int main() { ... if (Fp1 == NULL) ERRORE = 1; ...
return ERRORE; }
Nel mondo delle interfacce grafiche, invece, dove è l'utente a decidere che cosa far fare all'applicazione, i vari clic del mouse o apertura di menu etc. sono detti eventi. Un errore è semplicemente un altro evento, e sta poi alla routine che gestisce gli eventi arrabattarsi per gestire l'errore. Non faccio esempi che qui si dilungherebbero troppo.
!!!!La via OOP alla gestione di Errori ed Eccezioni I linguaggi OOP (tutti) gestiscono le Eccezioni in questo modo: un'Eccezione è un Oggetto, né più né meno, che viene istanziato nel momento in cui si verifica un'anomalia.\\ Questa creazione dell'oggetto si chiama "''lancio''", in inglese "''throw''".\\\
La teoria sottostante è quella della patata bollente: io lancio la patata bollente (la mia eccezione) e qualcuno dovrà afferrarla ("''catch''"), e quel qualcuno è la parte del mio codice che si preoccupa delle eccezioni.\\\
In JAVA esiste la classe '''Throwable''', cioè "''gettabile''", ed Errori ed Eccezioni sono tutti derivati di questa. Esiste naturalmente una monumentale gerarchia di errori, l'uno figlio dell'altro, per rappresentare tutto ciò che può andare male in un programma, ed è tanta roba...\\ Le varie eccezioni ereditano da '''Exception''', gli errori da '''Error''', i due figli di primo letto di '''Throwable'''.\\\
Quindi, ho un mio bel metodo, e lo dichiaro così:
tipo mioMetodo(parametri) throws BruttaEccezione { ... }
E poi chiamerò questo [@mioMetodo@] all'interno di un costrutto [@try ... catch@]:
try { mioMetodo(valore); } catch (BruttaEccezione ahiahi) { ... // gestione dell'eccezione }
Che cosa succede in queste linee di codice?\\\
Innanzitutto, ho dichiarto che il metodo [@mioMetodo@], se va storto, lancia l'eccezione detta [@BruttaEccezione@] (posso averla inventata io, oppure esistere già in JAVA).\\\
Poi, dentro il [@try { ... }@] chiamo il [@mioMetodo@]. Chiamarlo da dentro il costrutto [@try { ... }@] mi assicura che, nel caso generi un errore, esso sarà catturato dal seguente costrutto [@catch { ... }@].\\ Infatti, il mio [@catch (BruttaEccezione ahiahi)@] riceve l'eccezione gettata da [@mioMetodo@], e poi se la gestisce come vuole.\\\
Posso anche non avere nessuna [@catch@]: l'errore arriva ma non reagisco. Oppure avere più di una [@catch@], una per ogni eccezione che mi aspetto di ricevere.\\\
Esiste infine la clausola [@finally {...}@] in cui si finisce anche se c'è qualcosa che il [@catch@] non ha preso. Quindi, il costrutto definitivo è
try { ... } catch (tipoEccezione nome) { ... } finally { ... // qui si viene comunque, errore o non errore }
Quando un metodo getta un'eccezione, il metodo si interrompe e ritorna a chi lo ha chiamato. Se questo chiamante non gestisce l'eccezione, si torna a chi ha chiamato il chiamante e così via. Si dice che l'eccezione si ''propaga''. Se nessuno la prende, arriva alla JavaVM e si blocca. Di solito cmq c'è qualcuno che prende l'eccezione.
!!!!I/O in JAVA JAVA gira su una Virtual Machine, cioè una macchina virtuale. Quindi, può girare su diversi sistemi operativi, come Linux, e anche su sistemi inoperativi come windows. Ognuno di questi sistemi, operativi o inoperativi, può gestire in modo diverso l'I/O. La JavaVM deve quindi ''astrarre'' dalle implementazioni specifiche, ed offrire al programmatore JAVA un'interfaccia comune a tutti.\\\
Innanzitutto, i '''file''' sono sequenze di dati di un certo tipo. Possono essere di tipo disparato, ma tutti i file hanno in comune certe cose: * sono identificati da nome e percorso * si aprono e si chiudono * posso accedere ad essi in lettura o in scrittura * si può posizionare la testina all'interno di essi
In JAVA ho la libreria JAVA.IO che incapsula il concetto di ''stream'', a noi già noto dal C. Lo ''stream'' è un flusso di dati, in arrivo o in partenza.\\ L' '''InputStream''' è il flusso in arrivo, mentre '''OutputStream''' è il flusso in partenza.\\\
Tutti gli ''stream'' hanno un'interfaccia comune, come è lecito aspettarsi:\\\
* InputStream -> * [@read();@] legge -> * [@skip();@] salta un certo numero di dati -> * [@mark();@] marca una posizione per poi poterci ritornare -> * [@reset();@] azzera la testina -> * [@close();@] chiude il mio ''stream'' \\\ * OutputStream -> * [@write();@] scrive -> * [@flush();@] svuota il buffer e lo scrive tutto (sincronizzazione) -> * [@close();@] chiude il mio ''stream''
E naturalmente ci sono tutte le classi che ereditano da ciò e sono specializzate ad esempio nella lettura di file di [@char@] e così via.
!!!!Serializzazione È un meccanismo JAVA che mi permette di salvare gli oggetti, anche quelli creati da me, in un certo formato, per poi recuperarli così come sono.\\ È JAVA stesso che decide come rappresentare i miei oggetti, basta che essi implementino l'interfaccia '''Serializable'''.\\\
Se invece voglio essere io a decidere come rappresentare i miei oggetti quando li salvo, devo implementare l'interfaccia '''Externalizable'''.
Changed lines 86-87 from:
I ''metodi'' sono funzioni, esattamente come quelle del C.\\
to:
I ''metodi'' sono funzioni, esattamente come quelle del C.\\\
Changed lines 158-216 from:
L'ereditarietà di interfiaccia si chiama ''subtyping'', mentre l'ereditarietà di realizzazione si chiama ''subclassing''.
to:
!!!!Interfacce e incapsulamento: modificatori Nella nostra definizione di Tipo di Dato Astratto, dicevamo che occorre dargli le precondizioni e gli assiomi.\\ Le interfacce si avvicinano al Tipo di Dato Astratto, nel senso che permettono di separare l'interfaccia dal tuorlo. Ma non permettono di dare precondizioni e assiomi. Quindi non sono veri Tipi di Dato Astratto(tm).\\\
Prima parlavo dei ''modificatori''. Servono proprio all'incapsulamento, perché mi dicono chi rimane nascosto e chi rimane visibile.\\\
''Public'' vuol dire che quel metodo è visibile: tutti quelli che hanno accesso alla mia classe lo possono vedere e quindi utilizzare.\\ ''Private'' è il contrario: solo gli altri metodi della mia classe possono vederlo, dall'esterno no: c'è un guscio impenetrabile sopra di esso. Nemmeno le classi che ereditano da me possono vederlo, è mio e basta.\\ ''Protected'' è una cosa diversa: vuol dire che al di fuori non lo può vedere nessuno, ma i miei eredi sì.
!!!!Ereditarietà e Polimorfismo Come avete visto sopra, posso far ereditare interfacce o classi ad altre classi: ho una classe ''super'', cioè superiore, da cui gli altri ereditano.\\\
Il '''principio di sostituibilità di Liskov''' si occupa di queste faccende legali relative all'ereditarietà.\\\
Una classe definisce un ''tipo'', le sue sottoclassi sono ''sottotipi''.\\ Dire che ''A è sottotipo di B'' vuol dire che ''ogni programma che utilizza un oggetto di classe A può utilizzare indifferentemente un oggetto di classe B senza modificare il comportamento logico'', proprio perché è un suo sottotipo.\\ Se la 126 e la Rover sono entrambi sottotipi di Automobile, il programma Pilota che prende come argomento un'Automobile può guidare indifferentemente la 126 o la Rover.\\\
Questo principio ci dice che una sottoclasse non può restringere il comportamento della classe genitrice. Se tutte le mie Automobili vanno a carburante, la 126 non può andare a pedali.\\\
Per seguire questo principio, in fase di progettazione si deve sudare un po' per capire chi eredita da chi. Ecco un bell'esempio: rettangoli o quadrati. Devo creare la classe Rettangolo e derivarne la sottoclasse Quadrato, o viceversa?\\\
Seguiamo la prima strada: creo il Rettangolo, ed il Quadrato deriva dal rettangolo. L'interfaccia del Rettangolo è questa:
double base, altezza; impostaBase(double); impostaAltezza(double);
Quindi il Quadrato erediterà questa interfaccia. Ma quando implemento la classe Quadrato?\\ Supponiamo che qualcuno dica al mio quadrato: [@impostaBase(23)@]. Essendo un quadrato, anche l'Altezza deve essere impostata a 23. Posso quindi implementare il metodo [@impostaBase(double)@] in modo che se aggiorno una cosa mi aggiorni anche l'altra automaticamente.\\\
Problema problema: quando ad un Rettangolo raddoppio la base, la sua area raddoppia. Quando ad un Quadrato raddoppio la base, la sua area quadruplica! Il comportamento logico ''non è lo stesso'': il principio di Liskov non è soddisfatto!!\\\
Allora devo fare così: l'interfaccia madre è Quadrato:
double base; impostaBase(double);
e il Rettangolo ''eredita'' da Quadrato e lo ''estende'':
class Rettangolo implements Quadrato { //la base e impostaBase(double) le ho ereditate double altezza; //lo aggiungo io impostaAltezza(double); //anche questo lo aggiungo io }
e così tutto funziona.\\\
Per dare un po' di termini, l'ereditarietà di interfaccia si chiama ''subtyping'', mentre l'ereditarietà di realizzazione (di classe) si chiama ''subclassing''.\\\
Il ''subtyping'' permette la compatibilità dei tipi: il sottotipo è Liskovianamente accettabile, ed è compatibile all'indietro con tutti i suoi antenati. Questo è già ''polimorfismo'', nello specifico ''polimorfismo per inclusione''.\\ Il controllo del polimorfismo lo si può fare anche staticamente: il JAVA prende la lista degli antenati e vede se tutto quello che faccio è accettabile.\\\
Come ho detto prima, invece, il ''subclassing'' prende dagli antenati anche il codice effettivamente scritto
[to be continued] ---- [[Torna alla pagina di Tetty -> Tetty]]
Added lines 63-70:
!!!!Creare vettori Semplice:
int[] lista = new int[300];
Posso creare array con qualsiasi tipo, comprese classi che creo io.
Added line 157:
L'ereditarietà di interfiaccia si chiama ''subtyping'', mentre l'ereditarietà di realizzazione si chiama ''subclassing''.
Added lines 143-148:
Si parla di ereditarietà multipla quando posso ereditare da più ''classi'', e in JAVA ciò non è permesso: posso solo implementare più interfacce.\\\
Qual'è il problema dell'estensione di Classe?\\ Il problema è che se eredito da due classi diverse ''che hanno implementato un metodo con lo stesso nome'', quale devo utilizzare? Il C++ permette sta cosa, e il procedimento per distinguere quale dei due metodi usare necessita di un avvocato per districarsene. Il JAVA semplicemente non lo permette.\\ Ciò deriva dal fatto che il JAVA è stato pensato per il Web: se eredito da un programma scaricato automaticamente da un sito, come faccio a controllare il codice come fa il C++ per stabilire chi eredita che cosa e così via? Non posso. Quindi niente ereditarietà multipla. E' molto meglio così.\\\
Changed lines 113-142 from:
e vuol dire che la mia 126 deve implementare tutti i metodi dell'interfaccia Automobile e tutti i metodi dell'interfaccia FortunaDrago.
to:
e vuol dire che la mia 126 deve implementare tutti i metodi dell'interfaccia Automobile e tutti i metodi dell'interfaccia FortunaDrago.\\\
Quando definisco un'interfaccia, posso definire solo le seguenti cose: * costanti * metodi astratti (cioè solo prototipi, devono essere le classi che implementano quell'interfaccia a scrivere l'effettivo codice: l'interfaccia mi dice solo che ''deve'' esserci un metodo con quel nome e quel valore di ritorno, ma poi non dice nulla di ''come'' vada implementato. OOP all'opera) * classi membro (includo altre classi) * interfacce membro (include altre interfacce)
Questi due ultimi punti meritano un paragrafo a sé.
!!!!Extends e Implements Parlando della OOP, dicevamo che è possibile estendere una classe o un'interfaccia.\\\
Le interfacce le abbiamo appena viste: basta che le implementi, e scriva tutti i membri che devono esserci, e ho implementato un'interfaccia. Abbiamo visto anche che posso implementare in una stessa classe più interfacce. Questa possibilità si chiama ''ereditarietà''.\\\
Invece la parolina [@extends@] mi fa estendere una classe già esistente: recupero i suoi membri ''già implementati'', e ne aggiungo di nuovi.\\ Per esempio, ho scritto la classe 126, e ora voglio una 126 particolare che ha anche l'autoradio:
class 126_tamarra extends 126 { //tutti i metodi di 126 sono già presenti! //ne aggiungo tre: int accendi_autoradio(); int alza_volume_autoradio(); int spegni_autoradio(); }
La differenza tra questo tipo di estensione e l'estensione di interfaccia è duplice: # se estendo una classe eredito anche i suoi bei metodi già implementati. Se voglio posso anche riscriverli # posso estendere 1 sola classe, mentre posso implementare diverse interfacce.
Changed lines 77-78 from:
I ''metodi'' sono funzioni, esattamente come quelle del C. Il ''costruttore'' è una funzione particolare, che appartiene alla Classe e non all'Oggetto, e serve per costruire effettivamente la mia classe. Se costruisco una classe [[126]], occorre obbligatoriamente sapere il numero di targa, e questo va passato come parametro del costruttore.
to:
!!!!Metodi, Costruttori e Attributi I ''metodi'' sono funzioni, esattamente come quelle del C.\\ Il ''costruttore'' è una funzione particolare, che appartiene alla Classe e non all'Oggetto, e serve per costruire effettivamente la mia classe. Se costruisco una classe [[126]], occorre obbligatoriamente sapere il numero di targa, e questo va passato come parametro del costruttore.
Added lines 92-113:
!!!!Interfacce Un' ''Interfaccia'' serve per stabilire solo l'interfaccia di una classe, ciò che è visibile all'esterno, il guscio.
interface Automobile { int accendi(); int spegni(); }
Quando stabilische che la mia classe implementa un'interfaccia, faccio così:
class 126 implements Automobile { int accendi() {...} int spegni() {...} }
Vuol dire che la mia classe 126 implementa l'interfaccia Automobile, e cioè ''deve'' fornire tutti i metodi specificati dalla mia interfaccia.\\\
Posso anche implementare più interfacce
class 126 implements Automobile, FortunaDrago { ... }
e vuol dire che la mia 126 deve implementare tutti i metodi dell'interfaccia Automobile e tutti i metodi dell'interfaccia FortunaDrago.
Added lines 63-89:
!!!!Dichiarazione di una classe Ecco come dichiarare una classe in modo formale
<modificatore> class <nome classe> extends <super classe> implements <interfaccia1> ... <interfaccia2> { <attributi> <costruttori> <metodi> }
<modificatore> ::= public, protected, private, abstract, static, final
Vediamo in dettaglio che cosa ciò significhi.\\\
I ''metodi'' sono funzioni, esattamente come quelle del C. Il ''costruttore'' è una funzione particolare, che appartiene alla Classe e non all'Oggetto, e serve per costruire effettivamente la mia classe. Se costruisco una classe [[126]], occorre obbligatoriamente sapere il numero di targa, e questo va passato come parametro del costruttore.
class 126 { 126(string numero_di_targa) { targa = numero_di_targa; } string targa; }
Questo costruttore di classe 126 prende come parametro il numero di targa, e lo assegna all' ''attributo'' [@targa@] della mia classe.\\ Come potete vedere, è una funzione sì, ma non ritorna niente. Nemmeno il void. Proprio niente.\\\
Changed lines 38-62 from:
Il problema dell'Unicode è che descrive ''in astratto'' il sistema delle tabelle, ma non dice niente sulla sua implementazione. Ecco perché sono nate le codifiche UTF: uno standard per implementare la definizione delle tabelle di caratteri inventata da quelli dell'Unicode. Si sa per esempio che in UTF il primo byte mi indica la tabella, il secondo il carattere, e così via. La specifica Unicode di per sé diceva solo: occorre indicare in modo diverso la tabella e il carattere, ma non diceva affatto come.
to:
Il problema dell'Unicode è che descrive ''in astratto'' il sistema delle tabelle, ma non dice niente sulla sua implementazione. Ecco perché sono nate le codifiche UTF: uno standard per implementare la definizione delle tabelle di caratteri inventata da quelli dell'Unicode. Si sa per esempio che in UTF il primo byte mi indica la tabella, il secondo il carattere, e così via. La specifica Unicode di per sé diceva solo: occorre indicare in modo diverso la tabella e il carattere, ma non diceva affatto come.
!!!!Come faccio a dichiarare un riferimento? E' semplice.
nomeClasse riferimento_a_classe; tipo[] riferimento_a_vettore; nomeInterfaccia riferimento_a_interfaccia;
e così via. Proprio come in C.\\\
Per accedere ai campi di una struttura di cui ho il riferimento, non uso più il [@->@] del C, ma mi limto al semplice '.'. Ecco un esempio per rinfrescare la memoria:
//La via del C struct gatto { int colore; };
struct gatto * Cheope = (struct gatto *)malloc(sizeof(struct gatto)); Cheope -> colore = 15;
//La via del JAVA gatto Cheope; Cheope.colore = 15;
Added lines 1-38:
(:title TettyJAVA:) [[Torna alla pagina di Tetty -> Tetty]] ---- !!!!JAVA JAVA è un linguaggio di programmazione OOP sviluppato dalla SUN.\\ Deriva dal C++, che è derivato dal C, quindi ha una sintassi a noi nota, e soprattutto nota a praticamente tutti i programmatori del mondo.\\\
Il C++ è un'estensione del C orientata agli oggetti. Presenta tutte le caratteristiche della OOP, anche se le implementa in un modo un po' complicato. La via del C pare essere sempre la più complicata. Rispetto al C++, il JAVA ha delle intuizioni piuttosto carine.
!!!!Il Riferimento e gli Object In JAVA, il concetto di puntatore è scomparso, ed è stato sostituito con il ''riferimento''.\\ Il tipo ''riferimento'' può anche lui puntare a una classe, ad un vettore, ad un interfaccia, al NULL. Il suo tipo base è il tipo ''riferimento'', ma poi assume il tipo dell'oggetto che sta maneggiando in quel momento.\\\
Tutto ciò che esiste in JAVA deriva dalla classe primigenia detta ''Object'': {+tutto+} è un'istanza di Object.\\ Quindi, un riferimento di tipo ''Object'' può riferirsi ad ogni cosa!\\\
Rispetto ai puntatori, i riferimenti hanno perso alcune caratteristiche che li rendevano potenti ma anche pericolosi da usare.\\ Innanzitutto è scomparsa la ''pointer arithmetic'': quella roba che ci permetteva di dichiarare un'array e di girarci dentro.
char lista[20]; char * gatto; gatto = lista; *(gatto + 10) = 'a'; // equivale a dire lista[10] = 'a';
Non è più possibile in Java prendere un riferimento e farlo puntare ad un indirizzo, perché si tratta di una cosa rischiosa. Infatti posso prendere un puntatore e dirgli di puntare a un indirizzo a caso, e mandare tutto il programma in SegFault, e nessuno me lo impedirebbe, e soprattutto è uno di quei bug che non si trovano mai.
!!!!La classe String La classe String è una sequenza di caratteri Unicode.\\ E' ''immutabile'': se voglio modificarla, la copio in un'altra stringa, vi copio il suo contenuto modificato, e reimposto il riferimento alla prima stringa in modo che si riferisca a questa copia modificata. Niente paura tutto ciò lo fa il JAVA da solo.\\ Questa procedura risolve tanti problemi legati al fatto che le [@char[]@] sono puntatori, ed è legittimo fare così:
char lista[20]; *(lista + 50) = 'f'; //Dove vado a scrivere? Chi mi controlla? Paura!
I caratteri Unicode sono un modo per rappresentare in tabelle tutti i caratteri che non ci stanno nella misera e ristretta tabella ASCII. L'ASCII è nato in America, e lì usano pochi caratteri. E gli arabi? I cinesi? E noi europei con le lettere con strani accenti etc.? Grave problema, perché ognuno di costoro estendeva a suo modo la tabella ASCII, rendendola incompatibile con l'estensione sviluppata in un altro stato.\\ Così si è pensato all'Unicode, che rappresenta in modo univoco un carattere, tramite un sistema di tabelle indicizzate: la tabella dei caratteri greci, quella dei caratteri lituani (??) e così via.\\ Il problema dell'Unicode è che descrive ''in astratto'' il sistema delle tabelle, ma non dice niente sulla sua implementazione. Ecco perché sono nate le codifiche UTF: uno standard per implementare la definizione delle tabelle di caratteri inventata da quelli dell'Unicode. Si sa per esempio che in UTF il primo byte mi indica la tabella, il secondo il carattere, e così via. La specifica Unicode di per sé diceva solo: occorre indicare in modo diverso la tabella e il carattere, ma non diceva affatto come.
|
|