Introduzione a Java - Dipartimento di Ingegneria dell`Informazione

annuncio pubblicitario
Introduzione a Java
Jacopo Torrini
Dipartimento di Sistemi e Informatica
Laboratorio di Tecnologie del Software
[email protected]
Introduzione
●
Il linguaggio Java è un linguaggio di alto livello con le
seguenti caratteristiche:
●
Semplice
●
Object oriented
●
Distribuito
●
Multithread
●
Dinamico (caricamento e linking)
●
Architecture neutral (window system, processor)
●
Portabile (byte code, standardizzazione tipi di dati)
●
Alte performance (JIT compiler)
●
Robusto (Strict compile-time and run-time check)
●
Sicuro
Compilatore
●
Sorgente in file di testo .java
●
Compilazione con javac e creazione di .class
●
Il prodotto è bytecode eseguito da Java VM
Esecuzione
●
●
ll programma viene lanciato col comando java
Lo stesso bytecode può essere eseguito su
sistemi differenti
Java Platform
●
●
Con platform si intende un
ambiente hardware o software
nel quale un programma viene
eseguito
La Java platform è un ambiente software
composto da 2 componenti:
●
Java Virtual Machine (VM)
●
Java Application Programming Interface (API)
Java API
Installazione
●
●
●
Per l'esecuzione è necessaria soltanto una JRE
(Java Runtime Environment)
Per lo sviluppo è necessario scaricare la JDK
(Java Development Kit) che contiene tra l'altro
la JRE.
www.oracle.com - Downloads - Java for
Developers – Java Platform (JDK)
Hello World
●
Aprire un file di testo e scrivere il seguente
codice:
public class HelloWorld {
public static void main( String [] args ) {
System.out.println( "Hello world!" );
}
}
●
Salvare con nome HelloWorld.java
●
Con una finestra di terminale digitare:
●
●
javac HelloWorld.java
Per eseguire digitare
●
java HelloWorld
Concetti di base
●
Oggetto
●
Classe
●
Ereditarietà
●
Interfaccia
●
Package
Oggetto
●
●
Un oggetto nel mondo reale possiede due
caratteristiche:
●
Stato
●
Comportamento
Un oggetto software in modo simile:
●
●
●
Campi (Memorizzano lo stato dell'oggetto)
Metodi (Interazione con lo stato dell'oggetto e
comunicazione tra oggetti)
Incapsulamento
Classe
●
●
●
La classe rappresenta la definizione del tipo di
dato
L'oggetto è l'istanza di una classe.
Normalmente vengono create diverse istanze
della stessa classe.
Ereditarietà
●
●
●
Una classe può essere
definita estendendo un'altra
classe.
La nuova classe eredita le
proprietà e i metodi di quella
estesa.
La nuova classe può
estendere / modificare il
comportamento della classe
estesa.
Interfaccia
●
●
●
●
●
L'interfaccia di un oggetto rappresenta i metodi che l'oggetto
stesso espone verso il mondo esterno
In Java si può definire un interfaccia tramite la keyword interface
e la dichiarazione di un'insieme di metodi senza il body.
Una classe che implementa un'interfaccia garantisce al mondo
esterno di implementare i metodi definiti nell'interfaccia
Classi differenti (di gerarchie differenti) possono implementare la
stessa interfaccia (principio di sostituibilità)
Una classe può implementare più interfacce
Package
●
●
●
●
È un namespace che permette di organizzare
un set di classi e interfacce correlate
È possibile creare classi con lo stesso nome su
package differenti
Permette un controllo maggiore sull'accesso ai
metodi e i campi di un oggetto
Il nome del package definisce la struttura delle
cartelle dei file sorgente
Concetti di base del linguaggio
●
Variabili
●
Operatori
●
Expressions, statements e blocks
●
Control flow statements
Variabili
int cadence = 0;
int speed = 0;
int gear = 1;
●
Instance Variables (Non-Static Fields)
●
Class Variables (Static Fields)
●
Local Variables
●
Parameters
Operatori
Expressions, statements e blocks
●
Expressions:
●
Statements:
●
●
●
●
●
int cadence = 0;
anArray[0] = 100;
System.out.println("Element 1 at index 0: " +
anArray[0]);
int result = 1 + 2; // result is now 3
if(value1 == value2) System.out.println("value1 ==
value2");
Assegnazione
Incremento e decremento (++, -- )
Invocazione metodi
Espressioni di creazione oggetti (new)
Blocks:
class BlockDemo {
public static void main(String[] args) {
boolean condition = true;
if (condition) { // begin block 1
System.out.println("Condition is true.");
} // end block one
else { // begin block 2
System.out.println("Condition is false.");
} // end block 2
}
}
Control flow statements
●
If-then
●
If-then-else
●
Switch
●
While e do-while
●
For
●
Break
●
Continue
●
Return
Classi
public class Bicycle {
// the Bicycle class has three fields
private int cadence;
private int gear;
private int speed;
// the Bicycle class has one constructor
public Bicycle(int startCadence, int startSpeed, int
startGear) {
gear = startGear;
cadence = startCadence;
speed = startSpeed;
}
// the Bicycle class has four methods
public void setCadence(int newValue) {
cadence = newValue;
}
public void setGear(int newValue) {
gear = newValue;
}
public void applyBrake(int decrement) {
speed -= decrement;
}
public void speedUp(int increment) {
speed += increment;
}
}
Ereditarietà
public class MountainBike extends Bicycle {
// the MountainBike subclass has one field
private int seatHeight;
// the MountainBike subclass has one constructor
public MountainBike(int startHeight, int startCadence, int
startSpeed, int startGear) {
super(startCadence, startSpeed, startGear);
seatHeight = startHeight;
}
}
// the MountainBike subclass has one method
public void setHeight(int newValue) {
seatHeight = newValue;
}
Dichiarazione classe
class MyClass extends MySuperClass implements YourInterface1, YourInterface2 {
//fields
//constructors
//method declarations
}
●
●
La classe deve essere dichiarata in un file col
nome uguale a quello della classe
(MyClass.java)
Per costruttori, metodi e campi si specificano i
modificatori di accesso:
●
●
●
●
private
protected
private
package (nessun modificatore)
Campi (variabili membro)
●
Campi (variabili membro)
private int a;
private String b;
private double c = 0.5;
●
La dichiarazione è composta da:
●
Modificatore di accesso
●
Il tipo del campo
●
Il nome del campo
●
Eventuale inizializzazione del campo
Metodi
public int doSomething( int par1, String par2 ) throws
Exception {
...
}
●
È composto da:
●
Modificatori di accesso
●
Tipo del valore di ritorno
●
Il nome del metodo (convenzioni)
●
La lista dei parametri (eventuali)
●
La lista delle eccezioni lanciate (eventuali)
●
Il corpo del metodo
Signature
Questi metodi vengono chiamati instance methods
Overloading dei metodi
●
●
È possibile utilizzare lo stesso nome per più metodi a patto che
abbiano signature differenti
Metodi con signature identiche ma tipi di ritorno differenti non sono
ammessi
public void
...
}
public void
...
}
public void
...
}
public void
...
}
draw(String s) {
draw(int i) {
draw(double f) {
draw(int i, double f) {
Metodi e campi statici
●
●
●
Un campo statico è condiviso da tutte le istanze della
classe in cui è definito. Viene chiamato class variable.
Un metodo statico può accedere alle variabili statiche.
Viene chiamato class method.
Il metodo o il campo si definiscono tramite la keyword
static:
●
●
●
static int a = 5;
public static void doSomething() { … }
Per accedere al metodo (o al campo) si usa la forma:
●
NomeClasse.nomeMetodo(...);
Passaggio parametri per valore
public class PassPrimitiveByValue {
public static void main(String[] args) {
int x = 3;
//invoke passMethod() with x as argument
passMethod(x);
// print x to see if its value has changed
System.out.println("After invoking passMethod, x = " +
x);
}
}
●
// change parameter in passMethod()
public static void passMethod(int p) {
p = 10;
}
Dopo l'invocazione di passMethod x non varia
Passaggio parametri per riferimento
public void moveCircle(Circle
// code to move origin of
circle.setX(circle.getX()
circle.setY(circle.getY()
}
●
circle, int deltaX, int deltaY) {
circle to x+deltaX, y+deltaY
+ deltaX);
+ deltaY);
//code to assign a new reference to circle
circle = new Circle(0, 0);
Nel metodo chiamante l'oggetto circle risulta
modificato
Restituzione di un valore
public int getArea() {
return width * height;
}
●
●
●
Il return deve contenere il valore del tipo specificato dal
metodo.
I metodi che non restituiscono valori (definiti come void)
non hanno bisogno di alcun return. È possibile
comunque utilizzarlo per uscire dal metodo senza
bisogno di raggiungere la sua fine.
È possibile restituire istanze di oggetti senza problemi
Costruttori
●
Il costruttore viene invocato alla creazione di un'istanza di una classe
●
Nome identico alla classe
●
Parametri differenziano più costruttori
●
Nessun valore di ritorno
●
Se la classe non dichiara alcun costruttore il compilatore ne crea uno
senza argomenti (default constructor)
public Bicycle() {
gear = 1;
cadence = 10;
speed = 0;
}
public Bicycle(int startCadence, int startSpeed, int startGear) {
gear = startGear;
cadence = startCadence;
speed = startSpeed;
}
Creazione istanza oggetto
Bicycle yourBike = new Bicycle();
Bicycle myBike = new Bicycle(30, 0, 8);
Garbage collector
●
●
Java non prevede un esplicito intervento del
programmatore per provvedere alla
deallocazione degli oggetti.
Tale compito è svolto automaticamente dalla
JVM, attraverso il processo denominato
garbage collection, che si occupa di ricercare
nell'heap gli oggetti non più referenziati e
deallocarli
La keyword this
●
Con una variabile:
public class Point {
public int x = 0;
public int y = 0;
}
●
Nel costruttore:
//constructor
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public class Rectangle {
private int x, y;
private int width, height;
public Rectangle() {
this(0, 0, 0, 0);
}
public Rectangle(int width, int height) {
this(0, 0, width, height);
}
public Rectangle(int x, int y, int width, int height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
...
Package
package com.mycompany.myproject;
class MyClass {
}
●
●
I package hanno una struttura
gerarchica che definisce la struttura
delle cartelle in cui sono presenti i file
sorgente.
I file compilati rispettano tale gerarchia
Modificatori di accesso
●
●
●
●
●
Si applicano alle classi, ai metodi e ai campi
public: rende l'elemento accessibile da parte di
tutte le classi dell'applicazione
protected: rende l'elemento accessibile da parte
delle classi del package e delle sottoclassi anche
di altri package
no modifiers (package): rende l'elemento
accessibile da parte delle classi del package
private: rende l'elemento accessibile solo alla
classe stessa
Interfacce
public interface Resizable {
public void setSize( int width, int
height);
public class Rectangle implements Resizable {
…
public void setSize( int width, int height ) {
this.width = width;
}
this.height = height;
}
●
●
●
Definisce un tipo, come una classe, ma contiene solo
la definizione di metodi (senza implementazione).
Non possono essere istanziate, solo implementate o
estese da altre interfacce.
È ammessa l'ereditarietà multipla tra interfacce
Ereditarietà
●
Overriding dei metodi di istanza
●
●
●
●
Un metodo di una classe può essere ridefinito (override) nella
sottoclasse. In questo modo è possibile modificare il
comportamento di una classe specializzando alcuni dei suoi
metodi
Il metodo ridefinito ha la stessa signature del metodo della
superclasse. Al più può ridefinire il valore di ritorno con una
sottoclasse del tipo della superclasse (covariant return type).
Il modificatore di accesso devono essere pari o meno restrittivi
del modificatore della superclasse
Il metodo ridefinito deve (dovrebbe/è consigliato) avere
l'annotazione @Override (si vedano le annotation)
Ereditarietà
●
Override di metodi di classe
●
●
Il metodo ridefinito nella sottoclasse nasconde il
metodo della superclasse
Il metodo invocato dipende quindi dalla classe da
cui si invoca:
–
–
Subclass.aMethod(...)
Superclass.aMethod(...)
Polimorfismo
●
●
●
Gli oggetti di una gerarchia di classi possono
essere trattati come oggetti della classe di base
Tramite l'override dei metodi ogni sottoclasse
specializza alcuni comportamenti di ogni
classe.
I metodi definiti nella superclasse possono
essere invocati indipendentemente su ogni
istanza di oggetti della gerarchia, ottenendo
risultati differenti a seconda del tipo.
Esempio di polimorfismo
public class Animale {
public String getVerso() {
return "";
}
}
public class Cane extends Animale {
public String getVerso() {
return "bau";
}
}
public class Gatto extends Animal {
public String getVerso() {
return "miao";
}
}
....
public static void main( String [] args ) {
Animale [] animali = new Animale[2];
animali[0] = new Gatto();
animali[1] = new Cane();
}
for( Aninale a : animali )
System.out.println( a.getVerso() );
La keyword super
●
Accedere ai membri della superclasse
●
●
super.aMethod();
Chiamare un costruttore esplicito della
superclasse (altrimenti viene chiamato quello
senza parametri)
●
MyClass( int a, int b ) {
super(a);
this.b = b;
}
Classi e metodi astratti
●
●
●
Un metodo può essere definito astratto se per
esso non si vuole dare un'implementazione
(come per le interfacce)
Una classe con metodi astratti deve essere
definita astratta.
Una classe astratta non può essere istanziata.
Object
●
●
La classe Object è la superclasse di ogni oggetto
(anche se non viene dichiarato con extends).
Definisce un'insieme di metodi utili:
●
●
●
●
●
●
●
clone: permette di creare copie dell'oggetto
equals: compara due oggetti per valore e non per istanza. Questo
metodo dovrebbe essere ridefinito nelle sottoclassi.
hashCode: Restituisce la chiave hash associata all'oggetto. Dovrebbe
essere ridefinito insieme a equals
finalize: chiamato dal garbage collector quando l'oggetto viene
finalizzato
getClass: Riporta la runtime class dell'oggetto
toString: Riporta una rappresentazione stringa dell'oggetto
Altri metodi per la sincronizzazione
Number e String
●
●
Esistono delle classi che rappresentano l'implementazione
oggetto dei tipi di dati primitivi (int, double ecc.)
Queste classi (Integer, Double ecc) hanno il pregio di avere
implementati un'insieme di metodi di utilità.
●
Derivano da Number
●
La classe String permette la gestione di stringhe di testo.
●
È un value object
●
Per la manipolazione di stringhe si utilizza StringBuilder
Collections
●
●
Le API Java contengono un vasto numero di
implementazioni di classi per la gestione delle
collezioni di valori (alberi binari, hash table,
vettori, liste concatenate)
Utilizzano i generics.
Eccezioni
●
●
Un'eccezione è un evento che occorre
durante l'esecuzione di un programma e che
interrome il normale flusso di esecuzione.
Viene lanciata a seguito di un errore ed è
rappresentata da un oggetto che contiene le
informazioni dell'errore stesso
Eccezioni
●
●
●
Quando un'eccezione viene lanciata,
il sistema di runtime cerca qualcosa
che sia in grado di gestire questa
eccezione.
L'eccezione viene quindi passata a
tutti i metodi del call stack.
Questo meccanismo si arresta
quando viene trovato il blocco di
codice che gestisce l'eccezione,
l'exception handler
Exception propagation
●
●
L'exception handler si
dice che esegue il
catch dell'eccezione.
Se nessun metodo
definisce l'handler,
l'eccezione viene
propagata fino al di
fuori del main che
provoca la
terminazione del
programma
Tipi di eccezioni in Java
●
Esistono due tipi di eccezioni:
●
Checked exception
●
Unchecked exception
●
Le prime estendono la classe Exception
●
Le seconde estendono la classe RuntimeException
●
Per lanciare un'eccezione si utilizza la keyword throw
●
●
Per catturare un'eccezione (exception handler) si
utilizza il costrutto try – catch – finally
Un metodo può dichiarare di lanciare un'eccezione
tramite la keyword throws
Checked exception
●
●
●
Le eccezioni di questo tipo lanciate in un
metodo hanno bisogno di un exception handler
esplicito (try – catch - finally).
In mancanza di esso, il metodo che le lancia
deve dichiarare la classe dell'eccezione
(throws).
Se un metodo lancia una checked exception, a
sua volta ha bisogno di un exception handler o
deve dichiarare di lanciare l'eccezione
Try-catch
try {
...
}
catch( SomeException e ){
...
}
finally{
...
}
__________________________________________________
try {
...
throw new SomeException( “An error occurred” );
...
}
catch( SomeException e ) {
e.printStackTrace();
}
Metodo che lancia un'eccezione
public void aMethod( int param ) throws SomeException {
...
throw new SomeException();
...
}
public void otherMethod() {
try {
aMethod( 4 );
}
catch( SomeException e ) {
e.printStackTrace();
}
}
Unchecked exception
●
●
Si utilizzano come le checked exception, ma
non è obbligatorio un exception handler o la
dichiarazione throws del metodo.
Servono per gestire errori di runtime non
previsti, quali
●
NullPointerException
●
IllegalArgumentException
●
ArrayIndexOutOfBoundsException
Finally
●
●
●
●
Il blocco finally deve essere messo in fondo ad un
blocco try-catch o ad un blocco try
Viene eseguito all'uscita di un metodo, sia che sia
stata lanciata un'eccezione o meno.
Serve per eseguire operazioni di finalizzazione quali
chiusura di uno stream.
Si può utilizzare finally senza catch a patto che il
metodo dichiari di lanciare l'eccezione. Se sollevata,
l'eccezione non viene gestita dal metodo ma viene
propagata al suo esterno. Il blocco finally viene
comunque regolarmente eseguito.
Try-catch-finally. Esempio
InputStream in = null;
try {
in = new FileInputStream (“/path/file”);
...
}
catch( IOException e ) {
e.printStackTrace();
}
finally {
if( in != null )
in.close();
}
Try-finally. Esempio
public void aMethod throws IOException{
}
InputStream in = null;
try {
in = new FileInputStream (“/path/file”);
...
}
finally {
if( in != null )
in.close();
}
Scarica