Docsity
Docsity

Prepara i tuoi esami
Prepara i tuoi esami

Studia grazie alle numerose risorse presenti su Docsity


Ottieni i punti per scaricare
Ottieni i punti per scaricare

Guadagna punti aiutando altri studenti oppure acquistali con un piano Premium


Guide e consigli
Guide e consigli


Parte pratica/programmazione di informatica, Sintesi del corso di Informatica gestionale

Elementi e linguaggi di programmazione, il linguaggio Java

Tipologia: Sintesi del corso

2019/2020

In vendita dal 18/09/2021

alessandra.grm
alessandra.grm 🇮🇹

4.4

(8)

26 documenti

1 / 25

Toggle sidebar

Questa pagina non è visibile nell’anteprima

Non perderti parti importanti!

bg1
Ad ogni codice di istruzioni corrisponde un dato circuito che si accende quando individua quella determinata
sequenza. L’insieme delle istruzioni quindi è brevettato, perché le circuterie associate sono costruite in un
determinato modo. Lavorare con un codice di istruzioni non è sempre ragionevole, quindi si preferisce lavorare con
dei simboli significativi che formano il linguaggio assembly (tuttavia è molto difficile al processore e complesso da
comprendere per l’essere umano)→ NECESSITA’ DEI LINGUAGGI DI ALTO LIVELLO
CONCETTI DI BASE SUI COMPUTER: LINGUAGGI DI PROGRAMMAZIONE, COMPILATORI E INTERPRETI
La maggior parte dei linguaggi di programmazione è stata progettata per essere facile da utilizzare e comprendere e
tali linguaggi vengono definiti linguaggi di alto livello (Java, Visual Basic, C++, C#, Python, ...)
l'hardware dei computer non è in grado di comprendere direttamente i linguaggi di alto livello pertanto,
prima che un programma di alto livello possa essere eseguito da un computer, deve essere tradotto in un
linguaggio comprensibile dalla macchina.
il linguaggio assembly è una rappresentazione simbolica del linguaggio macchina, più semplice da
interpretare da parte di una persona. Di conseguenza, il linguaggio assembly corrisponde in parte al
linguaggio macchina, ma necessita comunque di alcune piccole trasformazioni prima di poter essere
interpretato dal computer.
Il compilatore è quello strumento che opera una traduzione prendendo in ingresso una sequenza di caratteri e li
trasforma in sequenza di codici come output (codice oggetto in genere già eseguibile). La traduzione di un
programma da un linguaggio di alto livello, come Java, a un linguaggio di basso livello viene effettuata interamente o
in parte da un altro programma detto compilatore che elabora il programma scritto in linguaggio di alto livello in
modo che possa essere eseguito sul computer. Questa operazione è detta compilazione del programma. Una volta
compilato, è possibile eseguire il programma risultante quante volte si vuole, senza doverlo ricompilare.
la terminologia usata potrebbe ingenerare un po' di confusione, in quanto sia l'input sia l'output del
compilatore sono programmi.
per evitare di confondere le idee, il programma di input per il compilatore è chiamato programma sorgente,
detto anche codice sorgente (source code), mentre il programma in linguaggio macchina generato dal
compilatore è chiamato programma oggetto o codice oggetto
alcuni linguaggi di alto livello non vengono tradotti da compilatori ma da un altro tipo di programmi detti
interpreti.
a differenza di un compilatore, un interprete esegue ogni singola porzione di codice subito dopo averla
tradotta invece di tradurre l'intero programma in una sola passata.
utilizzare un interprete significa che mentre si esegue un programma la traduzione si alterna all'esecuzione.
Inoltre, la traduzione viene ripetuta a ogni esecuzione del programma.
A differenza del compilatore, l’interprete genera un’istruzione eseguibile dal processore e la esegue (=interpreta al
volo). Se tutti vedono la soluzione, è possibile clonarla e ciò genera un fallimento a livello di copyright da parte
dell’azienda; inoltre un altro problema è che il meccanismo di interprete è “sempre” più lento e meno efficiente
dell’approccio compilato, perché in questo caso bisogna caricarlo in memoria ed eseguirlo (fetch, decode and
execute), mentre nel caso dell’interprete bisogna compilare un’istruzione alla volta e quando si rilancia bisogna di
nuovo ripetere la stessa procedura (tradurre, eseguire e compilare) PRESENZA DELLO STEP DI INTERPRETAZIONE.
Permette di far girare lo stesso codice su circuiti diversi, ma la presenza dello step di interpretazione genera dei
problemi a livello di efficienza
RESERVE ENGINEERING (o ingegneria inversa) è l'analisi accurata di un prodotto (che può essere un dispositivo
elettronico, un software, etc.) al fine di riprogettare un secondo prodotto che riproduca le stesse funzionalità del
primo, o parte di esse, e che sia in grado di interfacciarsi al prodotto originale. E’ un metodo residuato dagli anni 80,
ma non è più umanamente possibile. Un programma opensource è un programma su cui è eseguibile un codice
sorgente, ma non è copiabile. Condividere un codice sorgente può essere utile per individuare facilmente degli errori
interni.
CONCETTI DI BASE SUI COMPUTER: BYTECODE JAVA
Il compilatore Java non traduce il programma nel linguaggio macchina specifico del computer su cui è stato
compilato, ma lo traduce in un linguaggio detto bytecode. Il bytecode non è un linguaggio macchina di alcun
computer, ma è il linguaggio macchina di una macchina virtuale simile a tutte quelle più diffuse. Tradurre un
programma scritto in bytecode nel linguaggio macchina di un computer effettivo è abbastanza semplice. Il
programma che effettua questa traduzione e una specie di interprete chiamato macchina virtuale Java (Java virtual
machine, JVM)
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13
pf14
pf15
pf16
pf17
pf18
pf19

Anteprima parziale del testo

Scarica Parte pratica/programmazione di informatica e più Sintesi del corso in PDF di Informatica gestionale solo su Docsity!

Ad ogni codice di istruzioni corrisponde un dato circuito che si accende quando individua quella determinata sequenza. L’insieme delle istruzioni quindi è brevettato, perché le circuterie associate sono costruite in un determinato modo. Lavorare con un codice di istruzioni non è sempre ragionevole, quindi si preferisce lavorare con dei simboli significativi che formano il linguaggio assembly (tuttavia è molto difficile al processore e complesso da comprendere per l’essere umano)→ NECESSITA’ DEI LINGUAGGI DI ALTO LIVELLO

CONCETTI DI BASE SUI COMPUTER: LINGUAGGI DI PROGRAMMAZIONE, COMPILATORI E INTERPRETI

La maggior parte dei linguaggi di programmazione è stata progettata per essere facile da utilizzare e comprendere e tali linguaggi vengono definiti linguaggi di alto livello (Java, Visual Basic, C++, C#, Python, ...)

  • l'hardware dei computer non è in grado di comprendere direttamente i linguaggi di alto livello pertanto, prima che un programma di alto livello possa essere eseguito da un computer, deve essere tradotto in un linguaggio comprensibile dalla macchina.
  • il linguaggio assembly è una rappresentazione simbolica del linguaggio macchina, più semplice da interpretare da parte di una persona. Di conseguenza, il linguaggio assembly corrisponde in parte al linguaggio macchina, ma necessita comunque di alcune piccole trasformazioni prima di poter essere interpretato dal computer. Il compilatore è quello strumento che opera una traduzione prendendo in ingresso una sequenza di caratteri e li trasforma in sequenza di codici come output (codice oggetto in genere già eseguibile). La traduzione di un programma da un linguaggio di alto livello, come Java, a un linguaggio di basso livello viene effettuata interamente o in parte da un altro programma detto compilatore che elabora il programma scritto in linguaggio di alto livello in modo che possa essere eseguito sul computer. Questa operazione è detta compilazione del programma. Una volta compilato, è possibile eseguire il programma risultante quante volte si vuole, senza doverlo ricompilare.
  • la terminologia usata potrebbe ingenerare un po' di confusione, in quanto sia l'input sia l'output del compilatore sono programmi.
  • per evitare di confondere le idee, il programma di input per il compilatore è chiamato programma sorgente , detto anche codice sorgente ( source code ), mentre il programma in linguaggio macchina generato dal compilatore è chiamato programma oggetto o codice oggetto
  • alcuni linguaggi di alto livello non vengono tradotti da compilatori ma da un altro tipo di programmi detti interpreti.
  • a differenza di un compilatore, un interprete esegue ogni singola porzione di codice subito dopo averla tradotta invece di tradurre l'intero programma in una sola passata.
  • utilizzare un interprete significa che mentre si esegue un programma la traduzione si alterna all'esecuzione. Inoltre, la traduzione viene ripetuta a ogni esecuzione del programma. A differenza del compilatore, l’interprete genera un’istruzione eseguibile dal processore e la esegue (=interpreta al volo). Se tutti vedono la soluzione, è possibile clonarla e ciò genera un fallimento a livello di copyright da parte dell’azienda; inoltre un altro problema è che il meccanismo di interprete è “sempre” più lento e meno efficiente dell’approccio compilato, perché in questo caso bisogna caricarlo in memoria ed eseguirlo (fetch, decode and execute), mentre nel caso dell’interprete bisogna compilare un’istruzione alla volta e quando si rilancia bisogna di nuovo ripetere la stessa procedura (tradurre, eseguire e compilare)→ PRESENZA DELLO STEP DI INTERPRETAZIONE. Permette di far girare lo stesso codice su circuiti diversi, ma la presenza dello step di interpretazione genera dei problemi a livello di efficienza RESERVE ENGINEERING (o ingegneria inversa) è l'analisi accurata di un prodotto (che può essere un dispositivo elettronico, un software, etc.) al fine di riprogettare un secondo prodotto che riproduca le stesse funzionalità del primo, o parte di esse, e che sia in grado di interfacciarsi al prodotto originale. E’ un metodo residuato dagli anni 80, ma non è più umanamente possibile. Un programma opensource è un programma su cui è eseguibile un codice sorgente, ma non è copiabile. Condividere un codice sorgente può essere utile per individuare facilmente degli errori interni.

CONCETTI DI BASE SUI COMPUTER: BYTECODE JAVA

Il compilatore Java non traduce il programma nel linguaggio macchina specifico del computer su cui è stato compilato, ma lo traduce in un linguaggio detto bytecode. Il bytecode non è un linguaggio macchina di alcun computer, ma è il linguaggio macchina di una macchina virtuale simile a tutte quelle più diffuse. Tradurre un programma scritto in bytecode nel linguaggio macchina di un computer effettivo è abbastanza semplice. Il programma che effettua questa traduzione e una specie di interprete chiamato macchina virtuale Java (Java virtual machine, JVM )

Il linguaggio intermedio deve essere interpretato, quindi non può essere subito eseguibile dalla macchina. Un’idea era quello di tradurre un linguaggio di alto livello in un linguaggio più vicino alla macchina anche se non capibile dall’essere umano

COMPILARE ED ESEGUIRE UN PROGRAMMA JAVA

1. PROGRAMMA IN LINGUAGGIO SORGENTE ( JAVA COMPILER )

2. TRADUZIONE IN LINGUAGGIO BYTECODE

3. SI UTILIZZA L’INTERPRETE CHE LO METTE IN ESECUZIONE ( JAVA VIRTUAL MACHINE )

Rispetto agli arbori di Java, la parte hardware si è evoluto a sufficienza in modo che la via di mezzo di Java offre ottime performance Il bytecode dona a Java un vantaggio importanti: la portabilità. Dopo aver compilato il programma Java in bytecode, è possibile eseguire il programma su qualsiasi computer dotato di una macchina virtuale Java, senza bisogno di ricompilarlo : questo vuol dire che è possibile inviare il bytecode a un altro computer attraverso Internet e aspettarsi che questo venga eseguito, indipendentemente dal sistema operativo utilizzato sul computer remoto, infatti questo è uno dei motivi per cui Java è particolarmente utile per lo sviluppo di applicazioni Internet

  • conoscere l'esistenza del bytecode è importante, ma nella quotidianità della programmazione non ci si accorgerà neppure della sua presenza.
  • normalmente si utilizzeranno due comandi: uno per compilare il programma sorgente Java nel corrispondente bytecode e l'altro per eseguire il programma.
  • iI comando di esecuzione indica all'interprete di eseguire il bytecode; sarà del tutto trasparente il fatto che il bytecode debba essere interpretato prima di essere eseguito.

STORIA DEL LINGUAGGIO DI JAVA

1991 : James Gosling e il suo team presso Sun Microsystems sviluppano un nuovo linguaggio di programmazione che deve funzionare con una vasta gamma di processori (chip) diversi. 1994 : il nuovo linguaggio, che ora si chiama Java, si rivela ideale per sviluppare browser web in grado di eseguire programmi via Internet 1995 : il browser web Netscape esegue programmi Java Il linguaggio Java si trova a metà tra un metodo compilato e un metodo interpretato installabile su qualsiasi elettrodomestico, infatti nasce come un linguaggio che potesse incrementare l’acquisto degli elettrodomestici sul mercato e successivamente fu adattato agli altri dispositivi

APPLICAZIONI E APPLET

  • applicazione : programma Java concepito per essere eseguito localmente su un computer.
  • a pplet : programma Java concepito per essere inviato via Internet ed eseguito su un calcolatore remoto (grande idea tecnologicamente limitata su cui nacque l’idea delle HTMLS→ JAVASCRIPT ) Il main è un modo per indicare alla macchina qual è il primo punto da cui iniziare ad eseguire (entry point del programma). Se per uno stesso progetto ci sono due main, Eclipse segnala i due entry point per indicare quale eseguire: per ogni programma che coincide con un progetto si dovrà avere unicamente un entry point perché in tal modo Eclipse sa quale mettere in esecuzione. L’idea fondamentale di Java è che nel linguaggio di programmazione ci sono degli oggetti con cui interagire all’interno dei quali ci sono degli insiemi di assiomi, chiamati metodi. In Java è obbligatorio il fatto che, prima di utilizzare una variabile, si deve dichiarare.

IL PRIMO PROGRAMMA JAVA

Analizziamo ora in dettaglio il programma appena visto: import java.util.Scanner Indica al compilatore che questo programma usa la classe Scanner.

  • possiamo pensare a una classe come a un frammento di codice che è possibile usare in un programma
  • questa classe è definita nel package java.util(abbreviazione per Java utility).
  • un package una libreria di classi già definite. public class PrimoProgramma { ... } Le righe all’interno delle graffe definiscono la classe PrimoProgramma

rendere visibile solamente una parte di questa capsula; l'incapsulamento è spesso chiamato information hiding (letteralmente nascondere le informazioni) L’information hiding è un meccanismo in cui dato un certo oggetto, si ha che alcune informazioni possono essere visibili e altre nascoste dall’esterno nel disperato tentativo di dominare la complessità dei sistemi software. L’idea del polimorfismo si basa sul fatto che ad un’istruzione possono essere associati significati diversi (la divisione ha due applicazioni diversi, nel caso della divisione tra numeri interi e tra numeri razionali→ due operazioni sinteticamente diverse); mentre, il concetto di ereditarietà si fonda sul concetto di gerarchia, ossia la tendenza di fare classificazioni (i singoli gruppi secondari ereditano le caratteristiche dai gruppi principali) Es. per verificare se uno studente può anche essere professore, bisogna fare riferimento al dominio applicativo Fare un programma vuol dire modellare un dominio applicativo, ossia scrivere “nero su bianco” le caratteristiche del prodotto da sviluppare. A coniare il termine bug è stato Von Neumann stesso, perché ha costruito un computer utilizzando una tecnologia non basata sui transistor, ma su valvole termoioniche(=circuito complesso dentro un’ampolla di vetro in cui c’è il vuoto spinto). Una variabile è una zona di memoria che si dichiara al compilatore come riservata a contenere una determinata informazione a cui assegniamo un significato. E’ caratterizzata da un nome facente parte del programma sorgente, ha un tipo di base (intero ed altri) e assume un valore(all’inizio potrebbe avere un lavoro casuale).

ISTRUZIONI DI ASSEGNAMENTO

  • il modo più semplice per assegnare un valore a una variabile (o per modificarlo) è quello di utilizzare un' istruzione di assegnamento. Per esempio, per assegnare il valore 42 alla variabile risposta, di tipo int, si può utilizzare la seguente istruzione: risposta = 42;
  • Quando il simbolo - viene utilizzato in un'istruzione di assegnamento viene detto operatore di assegnamento.
  • l'istruzione di assegnamento indica al computer di cambiare il valore memorizzato nella variabile posta a sinistra dell'operatore di assegnamento con il valore dell'espressione posta sul lato destro.
  • l'istruzione di assegnamento termina sempre con un punto e virgola. Il right value deve essere necessariamente un valore, mentre il left value deve essere necessariamente una variabile adatta a contenere il valore definito nel right value. L’operatore di assegnamento ha la funzione di distinguere tra left value e right value , quindi prende all’ingresso due operandi con significato diverso e copia il right value (deve essere qualcosa di calcolato e di completo) nel left value. Si dice anche che abbia dei side effects, perché distrugge il contenuto di A e copia all’interno il right value quindi ha un effetto distruttivo. (= ASSEGNAZIONE, mentre == TEST UGUAGLIANZA)
  • Un'istruzione di assegnamento ha quindi la seguente forma: variabile = espressione
  • espressione può essere un'altra variabile, un numero, oppure un’espressione più complicata, costruita utilizzando operatori aritmetici per combinare variabili e numeri.
  • vediamo qui di seguito alcuni esempi di istruzioni di assegnamento somma = 3.99; (il right value è già calcolato) primaIniziale = 'B'; punteggio = partiteVinte + bonus;(prima di copiare il valore bisogna eseguire la somma) uovaPerCestino = uovaPerCestino - 2; (uova per cestino deve essere prima definito)

UN ESEMPIO DI OUTPUT SU SCHERMO

  • System è una classe fornita dal linguaggio Java e è un particolare oggetto di questa classe.
  • println. è uno dei metodi dell'oggetto .;
  • La seguente riga mostra a schermo il valore della variabile uovaPerCestino seguita dalla frase "uova per cestino e". System.out.println(uovaPerCestino + "uova per cestino e");
  • In questo caso il simbolo + non indica una somma aritmetica ma una concatenazione: questa riga può quindi essere interpretata come un'istruzione per stampare il valore di uovaPerCestino seguita dalla stringa "uova per cestino e".

COSTANTI

  • il valore di una variabile può variare nel tempo. Un numero, per esempio il numero 2, non può mai cambiare: il suo valore resta sempre 2. In Java. termini come 2 oppure 3.7 sono chiamati costanti (constants) o letterali (literals).
  • le costanti in virgola mobile possono essere scritte in due modi: il modo semplice consiste nello scrivere le cifre decimali dopo il punto di separazione (2.5 è una costante in virgola mobile), mentre il modo “complicato” è simile alla notazione scientifica comunemente utilizzata in matematica e fisica(il numero 865000000.0 può essere scritto come 8.65 x 108 e l'equivalente in Java è la notazione in virgola mobile , ovvero 8.65e8 dove la e sta per esponente dato che sostituisce la moltiplicazione per 10 e l'elevamento a potenza.

COSTANTI CON NOME

  • Java fornisce un meccanismo che permette di definire una variabile, inizializzarla e far sì che questo valore non sia più modificabile. La sintassi è la seguente: public static final tipo variabile = costante ;
  • per esempio, l'istruzione che segue attribuisce il nome PI al valore costante 3.14159: public static final double PI = 3.14159;

COMPATIBILITA’ DI ASSEGNAMENTO

  • un valore può essere assegnato a una qualsiasi variabile il cui tipo compare alla destra del tipo del valore nell'elenco seguente: byte→short→int→long→float→double
  • in altre parole, un valore di tipo long può essere assegnato a una variabile di tipo float o double (oltre che, ovviamente, a una variabile long) ma non può essere assegnato a una variabile di tipo byte, short o int.
  • quello indicato non è un elenco arbitrario. ma dipende dal fatto arbitrario, ma dipende fatto che, spostandosi da sinistra a destra, i tipi diventano sempre più precisi o permettono valori di dimensioni maggiori o permettono di usare valori decimali.

CONVERSIONI DI TIPO

In Java (e nella maggior parte dei linguaggi di programmazione) una conversione di tipo ( type cast ) cambia il tipo di un valore: int. punti - (int)distanza; l'espressione è detta conversione di tipo, tuttavia questa conversione non modifica né la variabile distanza né il valore in essa contenuto: la variabile punti conterrà però la "versione int” del valore memorizzato in distanza.

  • se il valore di distanza fosse 25,36, il valore di (int) distanza diventerebbe 25.
  • int.punti conterebbe, quindi 25, ma il valore di distanza rimarrebbe 25.36; se invece il valore di distanza fosse 9.0? Si noti che ogni volta che si compie una conversione di tipo da double a int (o da un qualsiasi tipo in virgola mobile a un qualsiasi tipo intero) il valore non viene arrotondato. La parte che segue la virgola viene semplicemente scartata. Questa operazione è detta troncamento ( truncating ).
  • per esempio le seguenti istruzioni: double contoCena = 26.99; int numeroEuro = (int)contoCena; assegnano a numeroEuro il valore 26 e non 27; quindi il valore non viene arrotondato. Un operatore unitario ( unary operator ) è un operatore che possiede un solo operando (un solo oggetto cui viene applicato), come, per esempio, l’operatore – nell’assegnamento seguente: bilancioBancario= - costo Un operatore binario ( binary operator ) ha invece due operandi come gli operatori + e * nell’istruzione seguente: totale= costo+ (tasse*sconto)
  • occorre notare che uno stesso operatore può a volte essere utilizzato sia come operatore unario sia come binario. Per esempio, i simboli + e – possono fungere sia da operatori binari sia unari Si noti che ogni volta che si compie una conversione di tipo da double a int (o da un qualsiasi tipo in virgola mobile a un qualsiasi tipo intero) il valore non viene arrotondato. La parte che segue la virgola viene semplicemente scartata. Questa operazione è detta troncamento ( truncating ).
  • per esempio le seguenti istruzioni: double contoCena = 26.99; int numeroEuro = (int)contoCena;

METODI DI STRING

Una variabile string non è una variabile semplice, come int; si tratta di un oggetto appartenente alla classe String. Gli oggetti possiedono metodi e dati. Per esempio, gli oggetti della classe String memorizzano dati costituiti da stringhe di caratteri. I metodi forniti dalla classe string consentono di elaborare questi dati. La maggior parte dei metodi di String restituisce un valore. Per esempio, il metodo length restituisce il numero di caratteri presenti in un oggetto di tipo string. Quindi l'istruzione “Ciao!.length () ; restituisce il valore intero 4. L'invocazione di un metodo si ottiene scrivendo il nome dell'oggetto seguito da un punto (dot), dal nome del metodo e infine da una coppia di parentesi.

  • di solito i metodi vengono invocati su variabili, come nelle seguenti istruzioni: String saluto = "Ciao"; int n = saluto.length();
  • il termine sottostringa (substring) indica una porzione di stringa. Per esempio, la stringa definita dall'istruzione: String frase = "Java e' bello"; ha la sottostringa "bello" che inizia all'indice 8.

SET DI CARATTERI UNICODE

Un set di caratteri è una lista di caratteri a ciascuno dei quali è associato un numero.

  • il set di caratteri ASCII include tutti i caratteri normalmente usati su una tastiera inglese. Ciascun carattere ASCII è rappresentato con un numero binario che occupa un solo byte. Questa codifica fornisce quindi 256 caratteri ed è adottata da diversi linguaggi di programmazione.
  • iI set di caratteri Unicode include, oltre all'intero set ASCII, anche i caratteri utilizzati in lingue diverse dall'inglese. Un carattere Unicode occupa 2 byte e pertanto la codifica Unicode fornisce più di 65000 caratteri differenti.

NOMI SIGNIFICATIVI PER LE VARIABILI

  • il nome assegnato a una variabile dovrebbe suggerire lo scopo per cui viene utilizzata. Se la variabile contiene un tasso d'interesse, il nome potrebbe essere tassoInteresse.
  • in genere i nomi delle variabili sono costituiti da lettere e cifre. II nome di una variabile dovrebbe iniziare con una lettera minuscola (è una convenzione dei programmatori Java, in quanto i nomi con iniziale maiuscola vengono solitamente impiegati per le classi, come ad esempio string).
  • se un nome è costituito da più parole, queste possono essere evidenziate con l'iniziale maiuscola. come in tassoInteresse, numeroDiProve o tempoResiduo.

COMMENTI

  • la documentazione di un programma indica gli scopi e il funzionamento del programma; quelli ben realizzati sono auto-esplicativi (self-documenting) ovvero, grazie a uno stile di programmazione pulito e a una scelta oculata dei nomi degli identificatori, qualsiasi programmatore dovrebbe essere in grado di comprenderne il funzionamento semplicemente leggendolo.
  • sebbene sia utile sforzarsi di scrivere programmi chiari, spesso è necessario aggiungere alcune spiegazioni per comprenderne il funzionamento. Queste spiegazioni possono essere espresse sotto forma di commento.
  • i commenti sono note scritte all'interno del programma per facilitarne la comprensione, ma che vengono ignorate dal compilatore.
  • vi sono tre modi per inserire commenti nei programmi Java: 1. Uso della sequenza // all'inizio di un commento: tutto ciò che segue questi simboli fino alla fine della riga è considerato un commento e viene ignorato dal compilatore. Questa tecnica è utile per commenti brevi, come nell'istruzione seguente: String frase; //versione italiana
    1. Per scrivere commenti che si estendono su più righe occorre utilizzare la coppia di simboli /* e /: tutto ciò che è incluso al loro interno viene considerato commento e ignorato dal compilatore: / Questo programma mostra come configurare i d1 imitatori della classe Scanner / E La sequenza /* è necessaria quando si adotta il programma javadoc per estrarre in modo automatico la documentazione di un programma Java. **/****

*Questo programma mostra come configurare i delimitatori della classe Scanner /

ISTRUZIONE IF-ELSE SEMPLICE

  • il significato di un'istruzione if-else è analogo a quello di “se... allora... altrimenti” in una frase italiana. Quando il programma esegue un'istruzione if-else in primo luogo controlla il risultato dell'espressione posta tra parentesi dopo la parola chiave if. Questa espressione deve avere un risultato che può essere o true (vero) o false (falso).
  • se il risultato è true, viene eseguita l’istruzione successiva (prima della parola chiave else)
  • se il risultato è false, viene eseguita l'istruzione che segue l'istruzione else.
  • in altri termini, l'istruzione if-else permette di scegliere tra due rami ( branch ): il ramo if e il ramo else. Se occorre includere più di un'istruzione in ciascuno dei due rami definiti dall'istruzione if-else è sufficiente racchiudere le diverse istruzioni tra parentesi graffe {}. Un insieme di istruzioni racchiuse tra parentesi graffe é considerato come un’unica istruzione più ampia. Il codice seguente presenta un’istruzione che include due istruzioni: { System.out.println. ("Bene! Hai accumulato degli interessi attivi!”); saldo= saldo+ (TASSO_INTERESSE*saldo) / 12: } Questo tipo di istruzioni più ampie sono dette istruzioni composte ( compound statements ). Di solito le istruzioni composte non vengono utilizzate da sole e in un punto qualsiasi del programma, ma come sotto-istruzioni di istruzioni più ampie, come le istruzioni if-else. if (espressione booleana) istruzione 1_ else _istruzione __
  • se espressione_booleana é vera, cioè se genera il valore true, vien eseguita istruzione_1, altrimenti viene eseguita istruzione_
  • la sintassi senza il ramo else e la seguente: if (espressione_booleana) istruzione
  • se espressione_booleana é vera, viene eseguita istruzione, altrimenti istruzione viene ignorata e il programma prosegue con l'istruzione successiva.

ESPRESSIONI BOOLEANE

  • la forma più elementare di espressione booleana confronta due espressioni semplici, come in questi esempi: saldo >= 0 e tempo < limite
  • un'espressione booleana non deve cominciare né parentesi. Tuttavia è necessario racchiudere l'esp quando viene usata in un costrutto if-else
  • in Java si può negare un’espressione booleana facendola precedere dal simbolo!
  • per esempio: if (! (numero>=min)) System.out.println (“Troppo piccolo”); else System.out.println (“OK”); se la variabile numero non è maggiore o uguale a min, l’output sarà: Troppo piccolo, altrimenti sarà: OK
  • un'istruzione di controllo if-else può contenere qualsiasi sorta di istruzione. In particolare, si può annidare ( nest ) un'istruzione if-else all'interno di un'altra istruzione if-else.

System.out.println("Abortire la sequenza di lancio"); se non si utilizzasse una variabile booleana, il codice precedente potrebbe risultare molto difficile da decifrare, come nell'esempio che segue: if ((temperatura <= 100) && (propulsione >= 100) && (pressioneCabina > 30)) System.out.println("Iniziare la sequenza di lancio"); else System.out.println("Abortire la sequenza di lancio"); chiaramente è necessario assegnare in qualche modo il valore alla variabile booleana; questo lo vedremo più avanti. A una variabile booleana può essere assegnato il valore di un'espressione booleana utilizzando un operatore di assegnamento. L'operazione è analoga a quella utilizzata per assegnare un valore a una variabile di qualsiasi altro tipo. Le seguenti istruzioni, per esempio, assegnano alla variabile positivo il valore false int numero = - 5; boolean positivo = (numero > O);

  • sebbene le parentesi non siano necessarie, tuttavia facilitano l'interpretazione dell'istruzione. Java valuta le espressioni booleane adottando la stessa strategia che utilizza per valutare le espressioni aritmetiche. Per esempio, se la variabile intera punteggio nella seguente espressione valesse 95: (punteggio >= 80) && (punteggio < 90); la prima espressione (punteggio >= 80) sarebbe vera, mentre la seconda espressione (punteggio < 90) sarebbe falsa. L'intera espressione sarebbe quindi equivalente a: true && false; L'espressione booleana ha quindi valore false.

REGOLE DI PRECEDENZA

Così come si fa quando si scrivono operazioni aritmetiche, è meglio usare le parentesi per esplicitare l'ordine delle operazioni nelle espressioni booleane. Se si omettono le parentesi, Java effettua le operazioni nell'ordine specificato dalle regole di precedenza

ENUMERAZIONI

  • per restringere il contenuto di una variabile a un certo insieme di valori, si può definire la variabile di tipo enumerazione ( enumerated data type o enumeration ). Un'enumerazione elenca solo i valori legittimi per una certa variabile. Per esempio, l'istruzione seguente definisce PunteggioFilm come enumerazione: enum PunteggioFilm {E, B, P}
  • si noti che i valori E, B, P non sono racchiusi tra apici perché non sono valori di tipo char

CICLI IN JAVA

  • la parte di programma che ripete un'istruzione o un gruppo di istruzioni è chiamata ciclo (loop).
  • l’istruzione o il gruppo di istruzioni che vengono ripetuti nel ciclo sono chiamati corpo (body) del ciclo.
  • ogni ripetizione del corpo del ciclo è chiamata iterazione del ciclo.

ISTRUZIONE WHILE

  • un modo per definire un ciclo in Java è tramite l'utilizzo dell'istruzione while, detta anche ciclo while ( while loop )
  • un'istruzione while ripete più e più volte l’azione definita nel corpo del ciclo finché un'espressione booleana di controllo rimane vera. Quando l'espressione diviene falsa, la ripetizione termina.
  • tutti i cicli while sono strutturati in modo analogo a quello del Listato 4.1. Il corpo del ciclo può essere costituito da una sola istruzione. anche se di solito è formato da un'istruzione composta.
  • la forma più comune di un ciclo while è la seguente:

while (espressione_booleana) prima_istruzione seconda istruzione … ultima istruzione_

ISTRUZIONE DO-WHILE

  • l' istruzione do-while , detta anche ciclo do-while ( do-while loop ) è molto simile all'istruzione while.
  • la differenza principale consiste nel fatto che il corpo di un ciclo do-while viene sempre eseguito almeno una volta, mentre nel caso del ciclo while il corpo del ciclo potrebbe anche non essere mai eseguito.

ISTRUZIONE FOR

  • l' istruzione for , detta anche ciclo for permette di scrivere facilmente un ciclo controllato da un contatore.
  • lo pseudocodice seguente definisce un ciclo la cui iterazione si ripete per tre volte, ed è controllato dal contatore conteggio. Fai quanto segue per ciascun valore di conteggio da 1 a 3: Visualizza il conteggio

USARE UNA VIRGOLA IN UN’ISTRUZIONE FOR

Un'istruzione for può anche eseguire più istruzioni di inizializzazione. Per usare più istruzioni di inizializzazione basta separare le istruzioni con una virgola, come vediamo qui: for (int numero = l, int prodotto = 1; numero <= 10; numero++) prodotto = prodotto * numero; Questo ciclo inizializza la variabile numero con il valore 1 e in più inizializza la variabile prodotto con il valore 1. Si noti che in questo caso, per separare due azioni di inizializzazione è stata utilizzata una virgola, non un punto e virgola. La virgola utilizzata in questo contesto viene detta operatore virgola (comma operator). Se nel corpo non si influisce su nessuna delle variabili, metodi o condizioni del ciclo while, accade che si verifica un ciclo infinito (loop), quindi se un’espressione è vera e nessuno la modifica, il ciclo continuerà ad essere vero all’infinito. Ciò è un problema perché ciclo infinito vuol dire avere un programma che non giunge mai al termine. Materialmente il ciclo while e do-while hanno entrambi un corpo e un testo da valutare, ma il primo esegue direttamente il testo mentre il do-while esegue prima il corpo e poi il testo. Una conseguenza immediata è che:

  • il while implica che il corpo venga eseguito 0 o n volte;
  • il do-while invece implica che il corpo venga eseguito 1 o n volte; E’ anche possibile eseguire un programma usando il while o il do-while. Quindi il do-while viene utilizzato quando si sa per certo che un’istruzione venga eseguita almeno una volta ma entrambi i costrutti hanno stessa potenza espressiva. L’esperienza ci fa dire che banalmente sono due forme equivalenti e utili a migliorare la leggibilità del codice. Il while e il do-while continuano ad operare quando l’istruzione risulta essere vera.
  • un’altra espressione equivalente ai primi due è il for, ma include un plus espressivo;
  • una variabile è visibile solo dal momento in cui viene dichiarata, ha uno scope;

Quali sono le caratteristiche di una variabile?

Una variabile è caratterizzata da cinque aspetti fondamentali nel linguaggio di programmazione:

  1. NOME (le variabili devono avere un nome significativo);
  2. VALORE (occorre che la variabile sia inizializzata);
  3. TIPO (int, float, double, scanner);
  4. VISIBILITA’ (è definita nel blocco in cui è definita e nel sotto-blocco in cui è dichiarata);
  5. TEMPO DI VITA ;

RAPPRESENTAZIONE DEGLI ALGORITMI

➢ LINGUAGGIO NATURALE

➢ DIAGRAMMA A BLOCCHI

➢ PSEUDO CODICE

  • si specifica il tipo(double) e il nome della variabile;
  • la misura del raggio 2 viene passata per valore al parametro formale raggio di tipo double come se fosse un’assegnazione in tutti gli effetti di tipo double raggio=2; Nel caso del raggio si ha un unico valore, mentre se si utilizza il calcola somma bisogna utilizzare due parametri, ossia due numeri (ad esempio si usano 2 e 3 la cui somma restituisce il valore 5): il passaggio per valore consiste in int x=2 e int y=3→ il passaggio degli argomenti avviene sempre per valore. Nel caso a destra, il main dichiara una variabile double di tipo intero e lo inizializza al valore 3.Inizialmente la variabile formale del metodo incrementa è indipendente dal dato, quindi ogni modifica del primo non influenzerà il secondo, infatti la prima operazione di stampa restituirà il valore 3; successivamente, viene fatta un’invocazione a incrementa(dato) che fa un passaggio per valore inizializzando la variabile formale e incrementandola attraverso il metodo incrementa(dato), quindi nel momento in cui si effettua un passaggio per valore, ossia dato = incrementaRitorna(dato) si crea un’assegnazione e la stampa restituirà il valore 4. Inoltre,esiste un altro metodo che viene chiamato passaggio per riferimento.
  • sebbene si possano utilizzare più istruzioni return all'interno del corpo di un metodo, è buona norma usarne solamente una;
  • inserire un'unica istruzione return vicino alla fine del corpo del metodo lo rende più semplice da leggere;
  • ciascun metodo appartiene alla classe in cui è definito; ciascun metodo restituisce un singolo valore oppure non restituisce alcun valore (metodo void);
  • la classe predefinita Math fornisce una serie di metodi matematici standard;
  • se si osservano i metodi della tabella si troveranno tre metodi simili, ma non identici: round, floor e ceil;
  • il metodo round arrotonda un numero al suo valore intero più vicino;
  • il metodo floor restituisce il numero intero più vicino minore o uguale del suo argomento;
  • il metodo ceil restituisce il numero intero più vicino maggiore o uguale al suo argomento; https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html STRUTTURA DATI =entità usata per organizzare un insieme di dati all'interno della memoria del computer, ed eventualmente per memorizzarli in una memoria di massa
  • ad ogni invocazione viene creata una casella di memoria contenente queste invocazioni;
  • finita l’esecuzione del metodo, il comando deve ritornare all’inizio;
  • quando si invoca un metodo, l'esecuzione passa al corpo del metodo invocato e viene creata in memoria una struttura dati, chiamata record di attivazione ;
  • le informazioni relative al metodo invocato includono parametri formali del metodo con gli argomenti attuali e le variabili locali al metodo con i valori man mano assunti;
  • il record di attivazione viene creato dinamicamente nel momento in cui il metodo viene chiamato e viene posto in cima a un'area di memoria denominata stack ;
  • metodi che invocano altri metodi originano una sequenza di record di attivazione in modalità LIFO;
  1. dato un input (=numero in virgola mobile) mostrare il numero e arrotondare alla 2° cifra significativa RISOLUZIONE numero di input= 9,234→ il computer dovrebbe stampare €9,24(in input si possono anche avere dei valori negativi) la somma data in input viene moltiplicata per 100 per prendere i due numeri significativi e poi applica l’operazione di arrotondamento risultato=924→ ARROTONDAMENTO si deve prendere la parte intera 9 e le cifre che rappresentano i centesimi 9,24 e stamparlo; per prendere i centesimi si utilizza l’operatore modulo che dà il resto di divisione per 100 924=9x100+24 da cui l’operazione di modulo % restituisce il 24, quindi si hanno due variabili dove il 9 rappresenta la parte intera e il 24 rappresenta la parte decimale;

nel caso in cui l’input sia negativo, si ha un caso speciale→ il resto dell’operazione modulo risulta negativo - 9,(-24) non ha senso, per cui si aggiunge un meno per renderlo positivo e poi si aggiunge alla fine numero di input=9, I ISTRUZIONE: 9,0235x100=902, II ISTRUZIONE: 902/100=9 (operazione con perdita di informazione) → %= OUTPUT FINALE= 9,2: l’output non è corretto, perché il risultato dovrebbe essere 9,02 quindi si modifica il codice: nel caso in cui il resto sia minore di 10, si aggiunge uno 0 in modo da avere lo 0 nel risultato quindi in tutto sono presenti due casi speciali da notare e decidere se gestire: GESTIONE NEGATIVO DELL’OUTPUT+ RESTO DELLA DIVISIONE< Il test va a vedere il valore di somma, quindi se è maggiore o uguale a 0 si stampa prima il simbolo di euro E e invoca il metodo scrivipositivo(somma) oppure l’altro cammino di esecuzione da else gestisce il fatto il caso di un numero negativo e invoca il metodo scrivipositivo(somma) sul valore positivo di somma, ma prima di stampare aggiunge il – println = si stampa l’intera linea e con l’ultimo carattere si ritorna accapo print = stampa solo un carattere

DECOMPOSIZIONE

  • quello che è stato fatto con questo pseudocodice è stato decomporre l'attività di visualizzazione del valore monetario in più sotto-attività;
  • se una sotto-attività è di grandi dimensioni, è bene suddividerla in sotto-attività ancora più piccole, da risolvere separatamente;
  • queste sotto-attività potrebbero a loro volta essere decomposte in attività più piccole, finché le attività non diventano abbastanza piccole da poter essere progettate e implementate facilmente; Gli array sono una speciale struttura dati in Java e si possono definire come un collettore di informazioni utilizzato per dichiarare una lista di variabili tra loro correlate e paragonate ad un elenco di variabili. Inoltre, è definito anche come un particolare tipo di oggetto (come lo scanner che permette di interagire con l’esterno), meglio considerato come collezioni di variabili dello stesso tipo.
  • ad ogni elemento è assegnato un indice della collezione (ad esempio, all’elemento 32 si assegna l’indice 0) MAIN= punto d’ingresso di un programma Java Quindi gli array rappresentano un modo elegante per dichiarare una collezione di variabili fra loro correlate e un array è una collezione di elementi dello stesso tipo paragonabile a un elenco di variabili , ma con una gestione dei nomi più immediata e compatta. Un array è un particolare tipo di oggetto , ma è più semplice considerarlo una collezione di variabili dello stesso tipo: in Java gli indici di un array partono da 0 - non da 1, né da qualsiasi altro numero E’ necessario specificare le dimensioni dell’array double[]temperatura= new double[7] (in questo caso si allocano sette celle che possono contenere un valore di tipo double)
  • in questo caso il parametro formale è un array di oggetti di tipo stringa; l’array temperatura contiene valori primitivi di tipo double; l’operazione new è una parola chiave di linguaggio con un significato ben preciso;
  • la lunghezza è uguale a 7 celle di tipo double e gli indici vanno da 0 a 6; In Java esiste un meccanismo chiamato inizializzazione ad un valore di default che significa attribuire un valore iniziale pari a 0. Se l’indice risulta minore di 7, si ha la terminazione dell’esecuzione del ciclo. Un array ha una sola proprietà accessibile: lenght ed è una variabile di istanza final, per cui il suo valore non è modificabile. All’interno di un programma non è possibile assegnare alla variabile di istanza lenght, in quanto è una variabile final.
  • l'operatore di uguaglianza == verifica se due array si riferiscono alla stessa area di memoria; l'operatore == non verifica se due array contengono gli stessi elementi Attraverso una valutazione dei parametri formali: int[]a= setA…(a); array=a→ ASSEGNAZIONE alla casella di memoria nel primo caso if(b==a), il programma stampa il fatto che sono diversi, perché puntano a celle di dimensioni diverse, mentre nel caso di if (equals(b,a))
  • un metodo Java può restituire un array e per fare ciò, specifica il tipo restituito dal metodo allo stesso modo con cui si specifica un parametro di tipo array; getMedia= metodo non proprio, ossia statico che restituisce un output e prende due argomenti di tipo intero restituendo una media ENTRY POINT =punto d’ingresso dell’esecuzione del programma Gli array sono collezioni di tipi omogenei a cui si può accedere utilizzando la notazione con le parentesi quadre con l’indice che si riferisce alla posizione dell’oggetto dell’array (il primo elemento in genere ha indice 0 e si riempie con elementi sempre contigui fino alla cella n-1). La difficoltà nell’utilizzo degli array non sta tanto nella sintassi, ma nella richiesta di ordine. Gli array sono una possibile risposta ad un problema legato agli algoritmi, ossia “cosa succede se si chiede di effettuare la media?”. Se gli elementi da calcolare sono 100, basterà dire che l’array sarà grande 100 e così via, a differenza degli algoritmi che non permettono di utilizzare tutti gli elementi inseriti tuttavia l’array non risolve il problema dalla radice in quanto:
  • la dimensione non è arbitraria;
  • è limitata, perché esiste un numero max di elementi da contenere quindi la maniera di programmazione è statica; L’approccio di ingrandire l’array non è una soluzione, perché un utente saturerà in ogni caso la dimensione e statisticamente la stragrande maggioranza di utenti non utilizzerà troppo caselle, mentre altri in minoranza ne sfrutteranno in numero maggiore alla capacità effettiva dando uno score negativo (si sovradimensiona la soluzione per gestire l’1% dei casi e per far ciò si utilizzano molte risorse). Quindi l’array non è una soluzione rispetto a dover salvare una collezione di elementi la cui dimensione non è nota a priori. Un inconveniente legato all’array è che se ad esempio un array è grande 200 caselle, un utente potrebbe utilizzarne solo 3, quindi il resto sarebbe sprecato→ è necessario riempire un array dall’inizio e in maniera contigua. In genere, si tende a distinguere tra dimensione fisica e dimensione logica dell’array. Ragionando solo in termini di tipi primitivi, la complessità della modellazione del problema diventa maggiore; gli esseri umani tendono a classificare il mondo in termini di segnali psico-cognitivi che ci circonda in termini di concetti e istanze di concetti. La programmazione mirata agli oggetti nasce come possibilità di implementare gli strumenti di modellazione. Gli oggetti di un programma possono rappresentare oggetti del mondo oppure astrazioni; una classe è la definizione di un tipo di oggetto. È come uno stampo (blueprint) per la costruzione di oggetti di un certo tipo.
  • si possono istanziare più oggetti della stessa classe;
  • una classe, inoltre, specifica le azioni che possono essere svolte dagli oggetti e come queste azioni vengono svolte;
  • si adotta una notazione più sintetica, detta diagramma delle classi UML (Universal Modeling Language) ; Una volta definiti oggetti e istanze, questi non hanno solo le proprietà che li caratterizzano ma anche le azioni che possono essere svolte su di esso. Oggetti diversi sono caratterizzati da gli attributi e i metodi che possono essere eseguiti o meno sull’oggetto (sono paragonabili alle funzioni) → materialmente si ha l’idea di classe come un insieme di oggetti definito da qualità, attributi e azioni dell’oggetto.

Se si vuole dare una formattazione standard ad una classe, si descrive la classe come un rettangolo contenente il nome della classe, i dati (ossia le caratteristiche che descrivono le istanze) ed eventualmente le azioni. Per ogni istanza si avranno diverse caratterizzazioni

FILE DELLE CLASSI E COMPILAZIONE

Indipendentemente dal fatto che si utilizzino le classi descritte in questo testo o classi scritte in altro modo, è necessario salvare ciascuna definizione di classe in un file distinto. Un file contenente la definizione di una classe ha lo stesso nome della classe stessa e usa come estensione la stringa .java: la definizione della classe Automobile sarà contenuta nel file Automobile.java. É possibile compilare una classe lava prima di avere un programma che la utilizzi. Il bytecode generato a partire dalla definizione di una classe e per effetto della compilazione, viene memorizzato in un file con lo stesso nome della classe, ma con l'estensione .class. Quindi, la compilazione del file Automobile.java genera il file Automobile.class. Una volta che il file Automobile.class è stato generato, non è più necessario ricompilare la classe per usare la sua definizione. Questa convenzione per i nomi si applica a interi programmi così come alle singole classi. L’ordine è uno dei pochi modi per poter gestire dei sistemi complessi 1 FILE=1 CLASSE → ogni file deve contenere una classe (rappresenta un concetto del dominio e in genere inizia sempre con una lettera maiuscola) attraverso una relazione 1: I dati e i metodi sono generalmente chiamati membri di una data classe ; le variabili vengono chiamate di istanza, in quanto caratterizzano il singolo concetto (ad esempio l’istanza di una pizza) In questo esempio, si alloca attraverso l’operazione new un oggetto balto di tipo cane, successivamente ci sono delle variabili di istanza che vengono inizializzate ad un valore arbitrario. Poi si invoca il metodo proprio dell’oggetto balto balto.scriviOutput()che permette di stampare il valore delle variabili dell’istanza dell’oggetto invocante. Se il metodo (nell’esempio a destra) fosse statico, non ci sarebbe visibilità e non si capirebbe a chi apparterrebbero gli attributi e inoltre, la classe non compilerebbe.

METODI DI ISTANZA

Un metodo di istanza è un metodo che viene invocato su un oggetto e che può manipolare lo stato dell'oggetto stesso. Nel Listato 8.2, l'istruzione balto.scriviOutput( ); invoca il metodo scriviOutput usando l'oggetto balto che è di tipo Cane. Un metodo di istanza definito in una classe viene invocato usando un oggetto di quella classe. L'oggetto prende il nome di oggetto chiamante ( calling object ) o oggetto ricevente ( receiving object ). Tutte le definizioni di metodo di istanza compaiono nella definizione della classe alla quale appartengono. Si invoca un metodo scrivendo il nome dell'oggetto che riceve l'invocazione, seguito da un punto, dal nome del metodo e da una coppia di parentesi che possono contenere gli argomenti. Ciascun metodo appartiene a una certa classe ed è accessibile a tutti gli oggetti creati da quella classe. Quando viene istanziato un oggetto, i valori delle sue variabili di istanza sono automaticamente inizializzate a valori di default che dipendono dal tipo con cui la variabile è stata dichiarata. La classe a sx ha tre variabili: nome (stringa), popolazione (primitivo intera) e tasso crescita (primitivo double) e un metodo proprio, chiamato leggiInput(). l’oggetto specieDelMese punta ad una casella di memoria della RAM rappresentato da una stringa di byte

  • nel caso del metodo statico, non c’è il concetto di metodo invocazione e per definizione, i metodi statici sono metodi di classe e non di oggetto

INFORMATION HIDING E INCAPSULAMENTO

Information hiding letteralmente vuol dire nascondere le informazioni. Sebbene questa frase sembri avere una connotazione negativa, rappresenta invece un grosso vantaggio. In un programma, la possibilità di nascondere alcune informazioni viene vista come una qualità del linguaggio che semplifica il lavoro dei programmatori e rende più comprensibile il codice.

I MODIFICATORI D’ACCESSO PUBLIC E PRIVATE

Come già osservato, il modificatore public, quando applicato a una classe, a un metodo o a una variabile di istanza, indica che qualsiasi altra classe può usare direttamente quella classe, metodo o variabile di istanza

tupla). Scanner è un oggetto implementato come un tipo di riferimento (4 byte che puntano a qualcosa di più grande che contiene un indirizzo dove i contenuti dell’oggetto sono memorizzati in campi statici o campi di dato)

  • in questo caso si poteva mettere lo Scanner tastiera e lasciare solo int numeroLettura Un costruttore può essere considerato come un metodo speciale per fare l’inizializzazione esplicita dell’oggetto, ma a differenza del metodo non ha un oggetto di ritorno e assume il nome della classe stessa. Il costruttore di default è costruttore senza parametro formale che effettua l’inizializzazione a zero di tutti i campi dati dell’oggetto per i tipi primitivi e per i tipi di riferimento (o oggetti come String) ad un valore speciale detto null(= è semplicemente una casella che non punta a nessuna parte). UTILIZZO DI CAMPI DATI PROPRIO E NON PROPRI Una cella di memoria è condivisa da tutte le istanze presente nel codice→ FATTORE GLOBALE (il campo dati statico è un campo globale di classe, mentre il campo dati privato è caratteristico solo dell’oggetto quindi è un FATTORE INDIVIDUALE). Un metodo proprio ha un oggetto di invocazione con il riferimento implicito this, mentre nel metodo statico c’è il concetto di classe di invocazione (e non di oggetto), quindi non ha a disposizione il riferimento implicito all’oggetto di invocazione.
  • la variabile statica può a sua volta essere definita come privata;
  • all’interno di uno stesso file ci possono essere varie condizioni di accessibilità; Integer è un oggetto di tipo intero primitivo, quindi la controparte di int e offre dei campi dati per interagire con un dato oggetto (è un costruttore deprecato che non viene utilizzato da Java 5, quindi al suo posto si utilizza un altro metodo: si assegna un valore di tipo primitivo ad Integer oppure si assegna ad un oggetto un valore di tipo primitivo o viceversa). OVERLOADING = sovraccaricare nel senso che una classe fornisce uno stesso metodo con stesso nome, ma segnatura diversa e in questo caso il nome è sovraccaricato (ad esempio utilizzando due o tre valori di tipo double, piuttosto che due valori di tipo char) Bisogna risolvere quel nome, ossia utilizzare un algoritmo che permette di invocare un metodo ad esempio, disambiguando attraverso dei criteri quale invocazione di massimo fare a tempo di esecuzione per cui si vede se è presente la compatibilità tra l’invocazione del metodo e il modo in cui viene invocato con dei controlli basati sul concetto di ereditarietà.
  • il carattere è un intero sottostante di cui si attesta un dato valore;
  • la regola della risoluzione dell’ambiguità consiglia di invocare il match perfetto tra i tipi di parametri formali e quelli di invocazione; Attraverso un oggetto è possibile implementare i tipi primitivi a precisione più alta, come espressi a 128 o 1024 bit. In questo caso sono definiti tre metodi non propri:
  1. BOXING = si assegna ad una variabile oggetto integer che viene inizializzato ad un tipo primitivo;
  2. UNBOXING = si spoglia l’oggetto e si considera solo il valore primitivo che si assegna ad un parametro formale;
  3. PRIMITIVE = prende come argomento un primitivo; Ci sono tipi oggetto che vengono rappresentati con un numero superiore di byte e vengono descritti partendo da questi metodi L’idea dell’enum è dichiarare un enumerativo che può assumere come valori solo delle possibili costanti ; i primi linguaggi di programmazione consideravano delle costanti come se fossero degli interi, nel senso che venivano enumerati a partire da 0, ad esempio CUORI=0, QUADRI=1 quindi era necessario elencarli e numerarli. Nella programmazione orientata agli oggetti, gli interi sono stati sostituiti da oggetti, per cui ogni istanza di una classe potrà assumere un determinato valore, come CUORI, QUADRI ecc. Il passo successivo è stato quello che siccome si ha un elenco enumerativo che non è altro che un’enumerazione dei tipi possibili è stato introdotto il costrutto for- each che è uno zucchero sintattico per un’istruzione di ciclo (come while, do-while e for) e si basa sull’idea che siccome si ha un insieme finito di oggetti, si potrà avere una quarta variante dell’istruzione di ciclo che si

applica su tutti gli elementi dell’enumerativo attraverso un processo di iterazione sull’insieme possibile dell’enumerativo. Per accedere a quest’ultimo Java aggiunge in automatico il metodo values dopo aver dichiarato la classe (la collezione di elementi deve essere molto piccola, perché il dominio restringe di tanto ed è caratterizzato da quelle costanti che non potranno variare e hanno un peso fondamentale in esso). L’espressione Seme.values() rappresenta tutti i valori dell’enumerazione. La variabile semeSuccessivo assume ognuno di questi valori a mano a mano che l’iterazione procede. Per questo motivo l’output del ciclo appena visto sarà: CUORI QUADRI PICCHE FIORI (degli esempi di enumerazione sono i topping, elenco delle regioni italiane o delle pizze) Per i dati variabili a lungo termine è consigliabile utilizzare altri costrutti alternativi alle enumerazioni. Un package è una collezione di classi correlate a cui viene assegnato un nome. Svolge il ruolo di libreria di classi, le quali possono essere utilizzate all'interno di un qualsiasi programma. Grazie ai package non occorre posizionare tutte queste classi nella stessa cartella del programma. Per comprendere al meglio è necessario sapere cosa sono le cartelle ( o directory ); che cosa sono i nomi di percorso ( path name ) delle cartelle; come il sistema operativo utilizza una variabile di percorso ( variabile path ).

  • un progetto piccolo tipicamente occupa dalle 100 alle 200 classi;
  • i package sono dei pacchetti di classe raggruppati uno accanto all’altro in piccoli gruppi;

PACKAGE↔ DIRECTORY DEL FILE SYSTEM SOTTOSTANTE

Un package è una collezione di classi raggruppate in una cartella, il cui nome deve corrispondere al nome del package. All'interno del package le classi sono disposte in file distinti , i cui nomi corrispondono al nome della classe. Ciascun file del package deve contenere all'inizio del file stesso: package nome_package ; niente può precedere questa riga a eccezione di righe bianche e commenti. Qualsiasi programma o classe può usare tutte le classi contenute in un package inserendo un'opportuna istruzione import all'inizio del file contenente il programma o la definizione della classe, anche se il programma o la definizione della classe non sono contenuti nella stessa cartella delle classi del package.

  • Per esempio, per usare la ClasseAusiliaria contenuta nel package generale.utilita, basta inserire all'inizio del file che si sta sviluppando: import generale.utilita.ClasseAusiliaria;
  • Per importare tutte le classi del package generale.utilita, si può usare: import generale.utilita.*;
  • l'asterisco indica l'intenzione di importare tutti i file del package; Al compilatore occorrono due informazioni: nome del package e cartelle elencate all'interno della variabile class path. La variabile class path non è una variabile Java, ma fa parte del sistema operativo: si tratta di una variabile d'ambiente. Quando Java cerca un package, inizia da queste cartelle, dette cartelle base del class path.
  • il nome di un package specifica la cartella che contiene le classi del package. Sia \programmijava\librerie una cartella base del class path e siano le classi del package in: programmijava\librerie\generale\utilita
  • in questo caso, il package deve avere il nome genere.utilita
  • il concetto di ereditarietà nasce dall’osservazione del modo con cui gli esseri umani intendono la realtà e l’esempio più classico è quando abbiamo a che fare con i nostri simili, infatti parlando tra di noi si cataloga l’immagine di una persona come essere umano quindi si ha la classe Persona;
  • la nostra mente tende a creare gerarchie di concetti (psicologia cognitiva);
  • l’ereditarietà è in modo intuitivo in cui si dice che la classe Professore o Studente è un tipo particolare della classe Persona senza utilizzare altri programmi, quindi le classi ereditano le caratteristiche della classe principale;

L’ ereditarietà ( inheritance ) permette di definire una classe più generale e di definire in seguito classi specializzate che aggiungono nuovi dettagli alla classe generale. Una classe derivata è una classe definita aggiungendo variabili di istanza e metodi a una classe esistente. La classe esistente, dalla quale è stata definita la classe derivata, è chiamata classe base , o superclasse. La relazione per cui Studente ha tutti i comportamenti di Persona è nota come relazione is-a. L'ereditarietà è utilizzabile solo se esiste una relazione is-a tra una classe e una potenziale classe derivata.