Lezione 1 - Perche' la programmazione ad oggetti?
L'attivita' del programmatore
Possiamo considerare l'attivita' del programmatore come quella di un ingegnere
che costruisce un ponte.La cosa piu' importante e' che il ponte non crolli,ovvero che il programma funzioni. La programmazione a oggetti permette di costruire
ponti che non crollano? Ahime no! Qualsiasi tecnica di costruzione programmi usiamo niente ci garantisce il
successo del programma. Questo e' dovuto solo all'abilita' del programmatore.
Allora a cosa serve la programmazione ad oggetti?Bene, se siamo riusciti a costruire un programma funzionante in qualche modo, come seconda cosa importante , vorremmo che il programma sia di facile manutenzione. Infine vorremmo poterlo
usare per costruire "altri ponti che non cadono". Ora la vecchia tecnica funzionale (programma=struttura di dati+funzioni) permette di
costruire programmi "monolitici" di difficile manutenzione e riuso.
La programmazione a oggetti invece spezzando il
programma in tanti oggetti indipendenti dovrebbe facilitare queste operazioni.
L'unica struttura di dati e libreria di funzioni del programma funzionale
si e' trasformata in una serie di oggetti ognuno dei quali ha una propria
struttura di dati e una libreria di funzioni.Come si vede un programma ad oggetti e' un'ulteriore astrazione del programma funzionale che potrebbe essere
considerato come un programma a un solo oggetto.
Per tornare alla nostra metafora ingegnieristica, ora stiamo costruendo ponti con moduli prefabbricati in modo da rendere piu' facile la costruzione di altri
ponti simili.
I linguaggi ad oggetti:un'ulteriore astrazione
Ora i dati sono racchiusi assieme alle funzioni negli oggetti:questa e'
l'ulteriore astrazione introdotta dai linguaggi a oggetti.E,come vedremo, i
dati sono accessibili solo attraverso speciali funzioni.
La struttura di dati che descrive lo stato di un oggetto viene definita ora dalle proprieta' dell'oggetto e realizzata con le variabili dell'oggetto. (Queste sono chiamate talvolta anche campi :fields in inglese).
Mentre le funzioni che descrivono il comportamento dell'oggetto diventano i metodi dello stesso.
La classe e' un pezzo di codice che descrive le proprieta' e i metodi
di un oggetto. Per cui ora un programma e' formato da una serie di classi.
Si dice anche che metodi e variabili sono membri della classe(in C++
infatti variabili e metodi si chiamano data members e member functions).
I linguaggi ad oggetto hanno particolari costrutti che permettono di trattare gli stessi oggetti.In particolare l'operatore new permette
di creare un oggetto descritto in una classe o come si dice di
instanziare lo stesso o crearne una istanza.Questo corrisponde
in pratica alla chiamata di un particolare metodo il costruttore
che ha lo stesso nome della classe e che provvede a inizializzare la struttura di dati dell'oggetto(in effetti secondo i puristi il costruttore non e' un metodo ).
L'accesso a una particolare proprieta' o metodo di un oggetto avviene attraverso l'operatore ".":nomeoggetto.nomeproprieta e nomeoggetto.nomemetodo().I due riferimenti si distinguono solo per la presenza delle parentesi tonde per i metodi.
Un caso concreto
Volendo costruire un programma che tratti
eventi della fisica delle alte energie con le loro tracce e i loro run,
nel caso della programmazione funzionale costruiremmo una struttura di dati
contenente Evento Traccia e Run piu' una libreria
di funzioni che fanno diverse operazioni su questi dati.
(Da notare che il nome funzione qui indica la stessa cosa di procedura,
routine,sottoprogramma).
Nella programmazione a oggetti partiremmo subito dai 3 oggetti
Traccia,Evento e Run e per ogni oggetto
definiremmo quindi le proprieta' e il comportamento.Le funzioni dell'approccio
procedurale appaiono ora come metodi all'interno delle classi.
Un programma utente ora invece di richiamare una serie di funzioni per
manipolare i dati di una struttura,
instanzia gli oggetti che servono e quindi chiede agli stessi oggetti
di fare certe cose invocando i loro metodi.
Il modo di affrontare il problema e' cambiato completamente: mentre prima
ragionavamo mettendoci nei panni del computer e definendo delle funzioni
che dovevano portare alla soluzione, ora ragionamo usando i termini del
problema e definiamo degli oggetti che modellano il problema e ognuno dei quali ha particolari capacita' che permettono di risolvere il problema. Quindi
non e' piu' il computer che disegna l'evento ma e' l'evento che disegna se
stesso come se ogni oggetto fosse un piccolo computer specializzato.
E' interessante confrontare la documentazione di un progetto software vecchio stile e uno ad oggetti.La relativamente semplice descrizione
della struttura dei dati dell'esperimento (una lista di "banche" tutte uguali
in formato ma di diverso contenuto) e' diventata un'enorme lista
di centinaia di classi ognuna con la propria interfaccia particolare: il risultato e' un
aumento di complessita' enorme per il povero programmatore!
Incapsulazione,Ereditarieta',Polimorfismo
Secondo i puristi,quanto detto finora , non basta per fare un linguaggio ad oggetti:sono necessarie inoltre le tre caratteristiche che adesso vedremo.
Chi usa un oggetto deve conoscere solo i nomi
delle proprieta' e dei metodi(ovvero la sua interfaccia) ma non ha bisogno di conoscere i dettagli dell'implementazione dello stesso che rimangono incapsulati,nascosti nello stesso:e' questa la cosiddetta incapsulazione dei linguaggi OO.Questa incapsulazione
dovrebbe isolare il codice di un oggetto evitando che il suo cambiamento possa influenzare il codice di un altro oggetto e si realizza attraverso particolari
attributi che proteggono l'accesso a classi,metodi e variabili che vogliamo rendere inaccessibili.In particolare incapsulazione significa proteggere le proprieta' rendendole accessibili solo attraverso speciali metodi di accesso (getValue) e di settaggio (setValue).
Se vogliamo modificare una classe non abbiamo bisogno di modificare
la classe originaria(anche se potremmo farlo) come succedeva nella
programmazione funzionale, ma i linguaggi a oggetti ci permettono di definire una
nuova classe che estende o eredita l'altra classe aggiungendo nuovi
metodi e proprieta' ed eventualmente ridefinendo (implementando)quelli della classe madre:
e' questa l'ereditarieta' dei linguaggi OO.
Sfruttando questo meccanismo i programmi sono in effetti delle gerarchie
di classi che condividono proprieta' e metodi:quando richiamiamo un metodo
di un oggetto proveniente da una classe in questa gerarchia non stiamo
richiamando un metodo ben definito, ma e' compito del linguaggio scoprire
all'atto dell'esecuzione quale metodo andra' richiamato.Questo e' il
polimorfismo dei linguaggi OO.Per questo non abbiamo per i linguaggi
ad oggetto la fase di link, ma l'aggancio a nuove classi avviene in
maniera dinamica all'atto dell'esecuzione.Questo particolare modo di lavorare
permette di scrivere programmi che hanno messaggi "generici" come
oggetto.disegna()
che funzionano con diversi tipi di oggetti ed anche con oggetti che saranno definiti solo nel futuro.
Incapsulazione,ereditarieta' e polimorfismo sono le 3 principali proprieta' che definiscono i linguaggi OO.
In concreto
Tornando ora al nostro esempio degli eventi, se ora vogliamo aggiornare
il codice, perche' si e' aggiunto un nuovo dato e dobbiamo modificare
il sottoprogramma di disegno degli eventi in modo da utilizzare questo dato,
nella programmazione ad oggetti questo non richiede alcuna modifica al
codice originale. Viene solo aggiunta una
nuova classe NuovoEvento aggiungendo le sole proprieta' e metodi modificati.
Le applicazioni precedenti funzionano ancora perfettamente perche' il codice
originario non e' stato cambiato.Inoltre ,se il nuovo codice ha solo ridefinito
vecchi metodi, i vecchi programmi funzioneranno anche con i nuovi eventi senza cambiare una riga di codice.
Nella programmazione funzionale siamo costretti a modificare il codice
precedente con possibili ripercussioni su tutte le applicazioni che gia' lo
usavano.Intanto dobbiamo aggiungere un nuovo dato in tutte le procedure. Poi
dovremo riscrivere tutte le procedure che usano il nuovo dato.
This,super e altri oggetti particolari
Nei linguaggi a oggetti le parole this e super hanno un significato speciale.This si riferisce al nome dell'oggetto del quale in questo momento stiamo
eseguendo qualche metodo,super si riferisce invece alla classe madre
di this.Infine in Java tutti gli oggetti sono discendenti da un'unica classe
: la classe Object. Una sottoclasse viene creata con l'istruzione
extends e puo' ereditare da una sola superclasse.
Cioe' in Java non abbiamo l'ereditarieta' multipla. La ridefinizione
di un metodo si dice in gergo override mentre l'overload
di un metodo si riferisce alla possibilita' di avere piu' metodi con
lo stesso nome ma con diverso numero e tipo di argomenti. In Java non
possiamo invece sovraccaricare(overload in italiano) gli operatori come +.
In Java tutto e' oggetto eccetto gli otto tipi primitivi ; percio'
per poter operare su di essi(come oggetti)
sono state create 8 classi Wrapper.
Classi Astratte e Interfacce: 2 classi molto speciali
La classe progenitrice di tutte le altre e' spesso una abstract class
della quale non si possono creare istanze e possiamo usarla solo estendendola.
Un'interfaccia(interface) e' anch'essa una classe astratta che contiene solo
metodi non implementati. Tali metodi possono essere implementati
da un'altra classe senza bisogno di estendere la classe ma implementando
la stessa con l'istruzione implements.Una classe puo' estendere un'unica
classe ma implementare un numero qualsiasi di interfacce. E' questa la maniera
di Java di realizzare l'ereditarieta' multipla.
Sia le classi astratte che le interfaccie permettono di descrivere
delle interfaccie che saranno implementate estendendo le stesse.
Ad esempio,in Java, per descrivere come deve essere scritto un oggetto
che lavori nel browser si e' definita la classe astratta Applet.
Chi vuole scrivere un programma che opera in una finestra di un documento Web
estende questa classe implementandone
i metodi come paint che indica cosa deve essere disegnato nella finestra.
Packages,strutture generate dall'ereditarieta' e strutture di dati
Nella programmazione ad oggetti e' facile confondersi se non si capisce
bene la differenza tra classi e oggetti e tra strutture formate da classi
e strutture formate da oggetti. Inoltre abbiamo strutture presenti solo
sul programma scritto e strutture che si creano all'atto dell'esecuzione
del programma. Gli oggetti,ad esempio,esistono solo all'atto dell'esecuzione
a differenza della classe che e' presente sia nel programma scritto che
all'atto dell'esecuzione sotto forma di variabili e metodi di classe.
Queste variabili e questi metodi vengono detti in Java statici perche'
realizzati attraverso la parola chiave static.
Per cui all'atto dell'esecuzione, per ogni classe usata, avremo le variabili e i metodi statici sempre presenti piu' un numero variabile(anche 0) di oggetti istanziati. Ogni oggetto istanziato ha le proprie variabili e i vari oggetti
attraverso queste variabili possono puntare l'uno all'altro creando una
struttura di dati:ad esempio una lista. Viceversa le classi,oltre
ad essere organizzate nella loro struttura gerarchica di ereditarieta' (che
ha come effetto all'atto dell'esecuzione che tutte le classi madri di una
classe usata sono caricate) sono raggruppate anche in packages(pacchetti).
La divisione in packages non ha niente a che fare con l'ereditarieta' e viene
introdotta per questioni di comodita'. Le classi di uno stesso package hanno
un'accesso facilitato alle proprie variabili e e ai propri metodi. Questo e' utile
per facilitare la scrittura di classi di servizio che servono solo
a realizzare la funzionalita' presente nelle classi pubbliche
del package.Tutte le classi di un package dividono la stessa cartella
che di solito ha lo stesso nome del package.Queste cartelle possono formare
una struttura gerarchica che non ha nessun particolare significato.Invece il singolo file,in Java,contiene una sola
classe pubblica e un numero qualsiasi di classi di servizio e puo' quindi essere considerato come un minipackage.
Il livello di accesso di una classe,variabile o metodo e' definito in Java tenendo conto di queste strutture.Questo
va infatti da private
(accesso consentito nella sola classe) a livello
di default (accesso consentito nel pacchetto), a protected
accesso consentito alle classi nel pacchetto e alle classi figlie in altri pacchetti; a public
accesso generalizzato.
Persistenza degli oggetti
La programmazione ad oggetti,mettendo l'accento sugli oggetti, cambia completamente il modo di considerare l'input/output. Prima si era
portati a considerare le strutture di dati in memoria come separate
e diverse dalle strutture di dati sulle memorie di massa, con istruzioni
di I/O che leggendo da nastro o disco popolano le strutture di dati
in memoria.In un linguaggio ad oggetti questo modo di porre il problema
e' (o dovrebbe essere) obsoleto: abbiamo solo oggetti persistenti
(cioe' con una copia su memoria di massa) che vengono copiati,quando
servono, tali e quali e poi eventualmente riscritti se cambiano di stato.
Percio' in un linguaggio ad oggetti invece di parlare di I/O si parla
di persistenza degli oggetti. Solo alcuni degli oggetti di un programma
saranno persistenti, mentre la maggioranza sara' del tipo transiente che viene distrutto quando il programma termina l'esecuzione.Java permette di leggere e scrivere oggetti
realizzando la persistenza ma una soluzione definitiva di questo problema
si avra' solo con l'affermarsi dei data base ad oggetti in contrapposizione
ai data base relazionali ora piu' in auge.
Scomposizione (ottimale) di un programma in oggetti
Trovare quali oggetti implementare per risolvere un certo problema, e'
una cosa difficile. Per questo,nel caso di grandi progetti con piu' persone,
esistono anche delle tecniche di analisi e disegno orientate
agli oggetti. Prima di cominciare a scrivere la prima riga di codice
c'e una lunga attivita' di progettazione simile a quella in uso nell'ingegneria
per decidere la struttura del programma rappresentandola con appositi
diagrammi.Un approccio possibile in questa fase viene indicato col nome
di L'UML o Unified Modeling Language.
L'UML non e' un linguaggio di programmazione ma una metodologia
che basandosi su una diecina di differenti tipi di diagrammi permette di
documentare l'attivita' di sviluppo del software dall'inizio alla fine.
Ha il vantaggio di non essere legato a un particolare linguaggio ad oggetti
e quindi di trattare classi e oggetti senza entrare nei dettagli dell'implementazione. Una classe viene rappresentata da un rettangolo diviso in 3 da due linee


in modo da poter contenere il nome, gli attributi e le operazioni. Una scritta
in corsivo rappresenta una classe o un'operazione astratta.Ovviamente gli attributi sono cio' che prima abbiamo chiamato proprieta' e le operazioni sono i metodi. E' possibile rappresentare anche le relazioni(statiche) tra le classi.
Sono previste relazioni di ereditarieta'/specializzazione/generalizzazione
(freccia con triangolo vuoto) e relazioni di associazione.La relazione di associazione prevede la possibilita' di rappresentare quattro tipi diversi di
associazione:composizione,aggregazione,associazione generica, dipendenza.
I quattro tipi si distinguono per essere rappresentati da frecce con rombo
pieno, freccia con rombo vuoto, semplice linea di collegamento piena,
semplice linea di collegamento tratteggiata.
Con questi simboli si crea il diagramma delle classi .
Questo viene preceduto nella progettazione dal diagramma dei casi d'uso
che permette di specificare le richieste dell'utente.Il diagramma di
sequenza permette di seguire nel tempo lo scambio di messaggi tra oggetti.
Seguono altri diagrammi che permettono di documentare ogni aspetto del
sistema.Altro esempio di
diagrammi UML.
Invece i Design Pattern ,nonostante il nome, vengono usati
durante l'implementazione in quanto aiutano a risolvere i problemi piu'
comuni che sorgono nel trattare gli oggetti.
I Design Patterns sono stati introdotti per la prima volta in un libro dello stesso nome della cosiddetta gang dei quattro(Gamma,Helm,Johnson e Vlissides) pubblicato
nel 1994.Questo libro ha avuto un grande effetto sulla comunita' dei programmatori ed ora parecchi dei 23 pattern presentati nel libro, sono diventati parte
del gergo se non delle implementazioni dei nuovi linguaggi incluso Java.
Ecco la classificazione originale:
- Creational Patterns :
Abstract Factory * Builder * Factory Method * Prototype * Singleton
- Structural Pattern :
Adapter * Bridge * Composite * Decorator * Facade * Flyweight * Proxy
- Behavioral Patterns :
Chain of Responsibility * Command * Interpreter * Iterator * Mediator * Memento * Observer * State * Strategy * Template Method * Visitor
Ad esempio Java ha implementato il pattern Iterator con l'oggetto Enumeration
(vedere la lezione 3 di questo corso). Il pattern Observer viene usato in diverse parti di Java quando uno o piu' oggetti hanno bisogno di aggiornarsi quando
un altro oggetto cambia stato.Ad esempio un oggetto vuole sapere quando il
download di un'immagine e' completato o quando l'utente ha fatto qualcosa.
Ogni pattern non fa che risolvere qualche problema ben definito in una maniera
ottimale ed evita di dover reinventare ogni volta la ruota. Ad esempio, per
fare un altro caso, il pattern Singleton risolve il problema di avere un oggetto in unica copia. In definitiva l'idea di base dietro ai design pattern (che
nonostante il nome hanno a che fare piu' con l'implementazione che col disegno in
quanto sono maniere standard di risolvere problemi ricorrenti) e' quello
di creare una nuova astrazione che vada oltre gli oggetti.
Invece al livello dei problemi eseguibili da parte di una sola
persona potete usare questa regola grossolana per decidere se il vostro programma e' stato diviso in un numero ottimale di oggetti:la lunghezza del codice
di ogni singola classe non dovrebbe superare le 2/3 pagine. Se una classe
diventa troppo grande allora e' arrivato il momento di definire nuovi oggetti.
In definitiva ...
La classe incapsula certi dati e i metodi per accedervi.Mentre prima
chiunque poteva modificare quei dati, ora dovete farlo passando attraverso
la classe e questo evita un sacco di problemi.
Un programma e' un insieme di oggetti che comunicano tra di loro mandandosi
dei messaggi. Questi messaggi, consistenti nella chiamata di un metodo,chiedono
all'oggetto che riceve il messaggio di fare qualcosa.
Potete pensare a un oggetto come un tipo di dati piu' complesso che si
aggiunge agli 8 tipi primitivi di dati.A questi dati puoi richiedere di fare
certe operazioni su se stessi, richiamando dei metodi.
Ogni oggetto ha una sua propria memoria che puo' contenere dati primitivi
e altri oggetti. Questo permette di creare degli oggetti di grande complessita'
partendo da oggetti semplici e impacchettandoli in un nuovo oggetto.
In un programma a oggetti potete inviare dei messaggi generici, a cui ogni
oggetto rispondera' a seconda della sua posizione nella gerarchia delle classi.
L'idea di fondo e' di far scrivere ai migliori programmatori degli oggetti
che poi possano essere riusati da tutti per costruire nuove applicazioni.
Java,con le sue librerie specializzate,fornisce migliaia di questi
oggetti pronti per l'uso. Questo ,non solo per facilitare il lavoro dei
programmatori, ma anche per fornire un ambiente di lavoro identico su
tutte le piattaforme su cui Java gira.Imparare a programmare in Java significa
innanzitutto conoscere queste librerie di classi.
Java Development Kit : JDK
Per programmare in Java occorre procurarsi il JDK della Sun (Java Development Kit) che e' la distribuzione ufficiale in una delle sue varie versioni.
Java viene fornito come una libreria di classi suddivise in packages e compresse nel formato zip piu' una serie di programmi eseguibili.
Talvolta questo e' gia' disponibile sul computer che
usate.Per scoprirlo e sapere quale versione e' disponibile basta dare il
comando(da finestra MSDos su PC):
java -version
Applicazione 1:Il piu' semplice programma Java
class Ciao{
public static void main (String args[]){
System.out.println("Ciao a tutti");
}
}
Per scrivere programmi Java usate un editore di testi come Wordpad su Pc
o vi su Unix.Copiate il programma e salvatelo in un file di nome Ciao.java
L'istruzione
javac Ciao.java
compilera' il programma' creando un file:
Ciao.class
Finalmente l'istruzione java Ciao
fara' eseguire il programma che scrivera' la frase Ciao a Tutti.
Applet 2:Il piu' semplice applet
Un applet e' un programma Java che gira all'interno di un browser.
import java.awt.*;
import javax.swing.*;
public class Ciao extends JApplet {
Display disegno;
public void init(){
disegno = new Display();
setContentPane(disegno);
}
class Display extends JPanel {
public void paintComponent(Graphics g){
super.paintComponent(g);
g.drawString("CiaoATutti",5,25);
}
}
}
Salvatelo su disco in un file Ciao.java come avete fatto con l'altro
programma e poi
compilatelo col solito comando:
javac Ciao.java
Questo crea il compilato Ciao.class. Per poterne
vedere l'esecuzione dovete inserire il programma
Java in una pagina Web. Questo si fa scrivendo un documento HTML con l'istruzione:
<APPLET CODE=Ciao.class Width=300 Height=50>
</APPLET>
che va salvato su disco col nome Ciao.html nella stessa cartella del programma Java. Ora basta leggere il documento col browser per poter vedere il programma in esecuzione. (Se fate queste operazioni su una cartella visibile dal Web e volete accedere all'applet con una URL
dovete probabilmente sproteggere i file Ciao.html e Ciao.class: su macchine Unix usate il comando
chmod 644 nomefile
Ma in fase di costruzione di un applet e' molto piu' comodo usare uno speciale programma del jdk chiamato appletviewer:questo lo si usa col comando
appletviewer Ciao.html
Cercate di familiarizzarvi con questa procedura che sara' usata in tutto il corso.
Programmazione a oggetti Java
Facendo un salto come complessità passiamo alla programmazione a oggetti.
Un programma invece di essere dei dati e delle routines e' un insieme di oggetti
che comunicano mandadosi messaggi. L'idea di base e' che un oggetto descrive
un "oggetto di tutti i giorni" con una serie di dati e una serie di routines
che trattano questi dati. Nel gergo un oggetto e' definito da una classe con
proprieta' e metodi. Le proprieta' non sono altro che delle variabili
che descrivono l'oggetto mentre potete pensare ai metodi come azioni che l'oggetto puo' fare o meglio comandi che gli potete inviare. (In effetti la differenza tra metodo e routine e' che un metodo e' una routine collegata a un singolo oggetto).Ora passiamo all'equivalente del programma CiaoATutti della programmazione a oggetti:un programma che non fa niente se non descrivere qualche oggetto della vita di tutti i giorni,in questo caso la moto.
/*classe Moto*/
class Moto{
String marca;
String colore;
boolean motoreacceso;
/*il costruttore*/
Moto(String m, String c){
marca = m;
colore = c;
motoreacceso = false;
}
/*metodi*/
void mostraTipo(){
System.out.println("La marca di questa moto e' "+marca+" e il suo colore e' "+colore);
if(motoreacceso == true)
System.out.println(".Essa ha il motore acceso.");
else
System.out.println(".Essa ha il motore spento.");
}
void accendiMotore(){
if (motoreacceso == true)
System.out.println("Il motore e' gia' acceso");
else {
motoreacceso = true;
System.out.println("Ora il motore e' acceso");
}
}
/*main*/
public static void main(String args[]){
Moto a = new Moto("Ducati","rossa");
Moto b = new Moto("Piaggio","blu");
a.mostraTipo();
a.accendiMotore();
a.mostraTipo();
b.accendiMotore();
b.mostraTipo();
}
}
In questo caso le proprieta' sono marca, colore e motoreacceso
mentre i metodi sono mostraTipo e accendiMotore.
Il costruttore e' invece un metodo speciale che ha lo stesso nome
della classe ed e' richiamato quando si crea un oggetto (dopo "new") per
inizializzare le variabili che descrivono lo stesso.In Java cioe' per
creare un nuovo oggetto bisogna dichiararlo e quindi chiamare il costruttore.
Vedi sopra:
Moto a = new Moto("Ducati","rossa");
Nota i messaggi all'oggetto creati con la notazione
nome_dell_oggetto.nome_del_metodo() ad es. a.accendiMotore().
Ed ora un esempio piu' utile. Riscriveremo il programma che fa la media di
una serie di numeri in modo da utilizzare una classe SerieNumeri.
public class SerieNumeri{
private int serie[];
private int n;
/*costruttore*/
public SerieNumeri(String s[]){
n = s.length;
serie = new int[n];
for (int i=0 ;i < n; i++){
serie[i] = Integer.parseInt(s[i]);
}
}
/*media*/
public double media(){
int totale = 0;
for(int i=0; i < n; i++){
totale += serie[i];
}
return((float)totale/n);
}
}
public class Media2{
static SerieNumeri a;
public static void main(String args[]){
a = new SerieNumeri(args);
System.out.println("La media e' "+a.media());
}
}
Le due classi vanno scritte su due diversi files SerieNumeri.java e Media2.java.
Per compilare ed eseguire usa i comandi:
javac SerieNumeri.java Media2.java
java Media2 2 4 8 5 63
Tipi di variabili Java
Il fatto che in Java oltre agli oggetti esistano anche dati primitivi comporta
che esistano di fatto due tipi di variabili:variabili collegate a oggetti
e variabili collegate a tipi primitivi. Questi due tipi di variabili hanno
comportamenti diversi che bisogna conoscere per poter interpretare correttamente
il funzionamento del programma.
Una variabile che si riferisca a un dato primitivo permette di trattare
direttamente il valore del dato, mentre una variabile che si
riferisce a un oggetto e' solo un puntatore alla zona di memoria
dove si trova l'oggetto.(Per evitare confusione coi puntatori del C++
si preferisce usare spesso la parola riferimento oppure handle
(in italiano manico)). Percio' l'effetto della dichiarazione:
int i;
Moto a;
e' completamente diversa nei due casi:
- viene allocata una zona di memoria e viene caricato l'intero 0.
- dopo la dichiarazione l'oggetto Moto ancora non esiste ed ha il valore
null
cioe' il cosidetto puntatore a terra.
Vediamo un altro pezzo di codice con comportamenti diversi nei due casi:
int i=1;
int j=2;
j=i;
String a = "Milano";
String b = "Torino";
b = a;
-
Dopo l'esecuzione del codice in memoria esistono 2 interi ed ambedue hanno valore 1.
- Dopo l'esecuzione del codice in memoria esiste un solo oggetto: la stringa "Milano" e sia a che b puntano ad esso.
Ecco un altro caso:
if (a == b)
-
Se a e b sono dati primitivi l'istruzione controlla se il valore di a e' uguale al valore di b
- Se a e b sono 2 oggetti, l'istruzione controlla se le 2 variabili puntano
allo stesso oggetto.Per controllare se 2 oggetti sono uguali bisogna usare
un apposito metodo e non serve l'operatore ==
Tipi di dati Java
Tipo |
Valore |
Valore di default |
Dimensione |
Classe Wrapper |
boolean |
true, false |
false |
1 bit | Boolean
|
char |
Unicode character |
\u0000 |
16 bits | Character
|
byte |
signed integers |
0 |
8 bits | Byte
|
short |
signed integers |
0 |
16 bits | Short
|
int |
signed integers |
0 |
32 bits | Integer
|
long |
signed integers |
0 |
64 bits | Long
|
float |
floating point |
0.0 |
32 bits | Float
|
double |
floating point |
0.0 |
64 bits | Double
|
I caratteri Unicode permettono di rappresentare i maggiori alfabeti mondiali.
Le classi wrapper servono quando dobbiamo usare un tipo primitivo come
oggetto. A queste classi sono inoltre associati dei metodi utili per
fare operazioni di conversione. Ad esempio per convertire un intero
n in una stringa di caratteri str , si scrive:
int n = 134;
String str = Integer(n).toString();
Esercizi della prima lezione del corso su Java2
- Create la vostra home page per il corso con un applet che mostra
la seguente scritta:Ciao a tutti , il mio nome e' xy.
Questa pagina va inserita nella cartella WWW
del vostro spazio sul disco di alboot. Mandate via mail la URL di
questa pagina a zito@ba.infn.it in modo che possa
essere attaccata alla home page del corso.
Collegate tutti gli esercizi che farete per il corso a questa pagina in modo da condividere il vostro lavoro con quello dei colleghi.
- Provate a creare una pagina Web decorata con applet presi dalla rete.
Se non sapete dove prendere questi applet usate java boutique.