Programmazione in Java Parte I: Fondamenti Lezione 1 Dott. Marco Faella Riferimenti Testi consigliati: ● Progettazione del software e design pattern in Java di C.S. Horstmann Apogeo Gli esempi di codice si possono scaricare da: www.apogeonline.com ● Core Java 2, (7a edizione), volumi 1 e 2 di C.S. Horstmann e Cornell Pearson/Prentice Hall Gli esempi di codice si possono scaricare da: www.phptr.com Riferimenti Per installare Java: ● ● java.sun.com Scaricare: ● JDK 6.0 (Java Development Kit: compilatore + JVM) ● JDK 6.0 + NetBeans ● Non è sufficiente JRE (Java Runtime Environment: solo la JVM) ● Editor: ultraedit, jEdit ● http://people.na.infn.it/mfaella Prerequisiti ● ● Questo corso presuppone la conoscenza di almeno un linguaggio di programmazione procedurale, come il C, il Fortran, una delle varianti moderne del BASIC, il Pascal, etc. Ad esempio, bisogna conoscere i seguenti concetti ● ● ● variabili ed espressioni procedure/funzioni istruzioni di controllo di flusso (almeno if-then-else e for) Il linguaggio Java ● ● ● ● ● ● ● ● ● ● ● ● ● Orientato agli oggetti Relativamente recente: 1995 Creato e controllato da Sun (ora Oracle) Ispirato alla sintassi C/C++, con numerose semplificazioni rispetto a quest'ultimo Attualmente molto utilizzato per applicazioni web lato server Ibrido tra compilato e interpretato Il compilatore crea il bytecode (linguaggio intermedio tra sorgente e macchina) La Java Virtual Machine (JVM) esegue (cioè, interpreta) il bytecode Si facilita la portabilità Sorgenti: .java Bytecode: .class Compilatore: javac JVM: java Il primo programma Java HelloWorld.java I tipi base di Java ● ● ● ● ● ● ● I tipi base sono nove: void, boolean, char, byte, short, int, long, float e double void è solo il tipo di ritorno delle procedure (metodi senza valore di ritorno) boolean può assumere solo i valori true e false char è un singolo carattere Le stringhe non sono un tipo base, ma una classe (String) byte, short e int sono tipi numerici interi, con segno ● byte: 8 bit, da -128 a 127 ● short: 16 bit, da -32000 a 32000 (circa, precisamente: da -215 a 215 -1 ) ● int: 32 bit, da -2 miliardi a 2 miliardi (circa, precisamente: da -231 a 231 -1) ● long: 64 bit, da -263 a 263 -1 float e double sono tipi numerici a virgola mobile ● float: 32 bit ● double: 64 bit Le conversioni implicite ● ● ● ● Tra tipi base esistono le seguenti conversioni implicite (o promozioni): ● Da byte a short, da short a int, da int a long, da long a float e da float a double ● Da char a int Le conversioni implicite sono transitive Se esiste una conversione implicita dal tipo x al tipo y, è possibile assegnare un valore di tipo x ad una variabile di tipo y Alcune di queste conversioni possono comportare una perdita di informazione ● Ad esempio: int i = 1000000001; // un miliardo e uno float f = i; Dopo queste istruzioni, f contiene un miliardo, perchè un float non ha abbastanza bit di mantissa per rappresentare le 10 cifre significative di i. Tipi base: esercizi 1) Inserire una dichiarazione (e inizializzazione) per la variabile i, in modo che il seguente ciclo sia infinito. while (i == i+1) {...} 2) Quante volte viene eseguito il seguente ciclo? for (double x=0; x<=1 ;x+=0.1) {...} Le classi e il loro contenuto ● ● ● ● Una classe è uno “stampo” per creare oggetti Contiene dati e gli algoritmi che li elaborano I dati: ● rappresentano lo stato dell'oggetto ● sono variabili di cui ogni oggetto avrà una copia ● vengono chiamate “campi istanza” Gli algoritmi: ● sono le funzioni associate alla classe ● vengono chiamate “metodi istanza” ● possono accettare parametri e restituire un valore ● vengono invocati a partire da un oggetto della classe ● Campi istanza e metodi istanza sono tutti chiamati membri della classe ● Un tipo particolare di metodo è chiamato costruttore, e serve a creare nuove istanze di quella classe I costruttori ● ● ● Sintatticamente, un costruttore si presenta come un metodo che: ● ha lo stesso nome della classe ● non ha tipo restituito Compito di un costruttore è di inizializzare lo stato (cioè, i campi istanza) dell'oggetto Viene invocato un costruttore ogni volta che si crea un nuovo oggetto, tramite il costrutto new Esempio: String s = new String(“ciao”); ● ● ● ● Una classe può avere più costruttori Se una classe non ha costruttori, il compilatore aggiunge automaticamente un costruttore senza argomenti (chiamato costruttore di default), che non esegue alcuna operazione Esempio: Strings.java Esempio di costruttore Data1.java Memory layout ● ● ● Si utilizzerà talvolta la nozione di “memory layout” di un programma Ci si riferisce ad una rappresentazione grafica dello stato della memoria ad un determinato punto di un programma Come primo esempio, dato il frammento di codice Java: class A { // campi istanza private String x; private int n; // costruttore public A(String x, int n) { this.x = x; this.n = n; } } ... A a = new A(“ciao”, 7); ● il suo memory layout può essere raffigurato come in Figura 1 Figura 1: Il memory layout del frammento di programma a fianco. Esempio di metodi Data2.java Riferimenti e passaggio di argomenti • A differenza di altri linguaggi orientati agli oggetti (ad es., il C++), non esistono variabili che contengono oggetti, solo riferimenti ad oggetti, ovvero variabili che contengono l'indirizzo di un oggetto • Tali riferimenti Java sono quindi simili ai puntatori del linguaggio C • Tuttavia, i riferimenti Java sono molto più restrittivi • Niente aritmetica dei puntatori (p++) e conversioni tra puntatori e numeri interi • Niente doppi puntatori • Niente puntatori a funzioni • Quindi, rispetto ai puntatori, i riferimenti Java sono meno potenti, più facili da utilizzare e meno soggetti ad errori al run-time • Java prevede solo il passaggio per valore: sia i tipi base che i riferimenti sono passati per valore • Non è possibile passare oggetti per valore, l'unico modo di manipolare (ed in particolare, passare) oggetti è tramite i loro riferimenti (ovvero, indirizzi) Passaggio di argomenti Parameters.java Passaggio di argomenti Stralcio di Parameters.java: public static void swap_str( Memory layout: String a, String b) { String tmp = a; a = b; b = tmp; x “Ciao” } y ... “Pippo” String x = “Ciao”, y = “Pippo”; swap_str(x, y); (prima di invocare swap_str) Passaggio di argomenti Stralcio di Parameters.java: public static void swap_str( Memory layout: String a, String b) { String tmp = a; a = b; b = tmp; x “Ciao” a } y ... “Pippo” String x = “Ciao”, y = “Pippo”; swap_str(x, y); (all'inizio di swap_str) b Passaggio di argomenti Stralcio di Parameters.java: public static void swap_str( Memory layout: String a, String b) { String tmp = a; a = b; b = tmp; x “Ciao” a } y ... “Pippo” String x = “Ciao”, y = “Pippo”; swap_str(x, y); b tmp (alla fine di swap_str) Soluzione degli esercizi 1) Inserire una dichiarazione (e inizializzazione) per la variabile i, in modo che il seguente ciclo sia infinito. while (i == i+1) {...} Soluzione: float i = 1000000000; // un miliardo Sommare 1 ad i non ne modifica il valore, in quanto un float non ha abbastanza cifre binarie nella sua mantissa per rappresentare il numero “un miliardo e uno”. Soluzione degli esercizi 2) Quante volte viene eseguito il seguente ciclo? for (double x=0; x!=1 ;x+=0.1) {...} Soluzione: infinite volte. La variabile x non assumerà mai esattamente il valore 1, perché 0.1 non è rappresentabile in maniera esatta con un double. Infatti, in rappresentazione binaria 0.1 è il numero periodico 0.0 0011. La morale di questi esercizi è che l'aritmetica in virgola mobile nasconde molte insidie. A tale proposito, si veda anche l'interessante disamina "How Java's Floating-Point Hurts Everyone Everywhere”, facilmente rintracciabile sul web.