Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
vuoi
o PayPal
tutte le volte che vuoi
SETTEMBRE, OTTOBRE, NOVEMBRE, DICEMBRE;}
//programma di test
public static void main(String[] args){
for(Mese m: Mese.values())
System.out.println(m);
//toString stampa il nome dell’oggetto
Mese[] mesi = Mese.values();
System.out.println(Arrays.toString(mesi));
}
Il secondo esempio indicato:
public enum Mese1{
GENNAIO (31), FEBBRAIO (28), MARZO(31), APRILE(30), MAGGIO(31),
GIUGNO (30), LUGLIO (31), AGOSTO (31), SETTEMBRE(30), OTTOBRE(31),
NOVEMBRE(30), DICEMBRE(31);
private int nGiorni;
Mese1(int nGiorni) {this.nGiorni=nGiorni;}
Public int nGiorni(){return nGiorni;}
}
//programma di test
public static void main(String[] args){
for(Mese1 m:Mese1.values())
Syestem.out.println(m+””+m.nGiorni());
}
//GENNAIO 31
//FEBBRAIO 28
//…
Classi Math e System
Math è una collezione di metodi (statici) matematici. System fornisce i riferimenti agli standard stream (int,
e vari metodi, tra cui il garbage collector.
out, err),
Alcuni metodi di Math
static double abs(double a)
static double cos(double a)
static double exp(double a)
static double log(double a)
static double max(double a, double b)
static random()//tra 0 e 1 compresi
static long round(double a)
static double sqrt(double a)
Esempio
Fornire un valore uniforme tra i due long l e h (l<=h).
public static long uniform(long l, long h){
double d = Math.random();
return Math.round(l+d*(h-l));
}
Alcuni metodi di System
Questa classe non è instanziabile perché manca il costruttore.
public final class System
static void arrycopy(Object src, int srcPos, Object dest, int destPos, int
lenght)
static long currentTimeMillis() //dal primo 1 gennaio 1970
static void exit(int status)
static void gc() //esegue la garbage collector
static InputStream in standard input stream
static PrintStream out standard output stream
ArrayCopy
public static void main(String[] args){
String[] s1 = {“alfa”, “beta”, “gamma”, “lamba”, “zeta”, “omega”};
String[] s2 = new String[3];
System.arraycopy(s1, 2, s2, 0, 3);
//
primo array, suo indice, secondo array, suo indice, n.elementi da copiare
System.out.println(Arrays.toString(s2)); //[gamma, lambda, zeta]
}
//alcune chiamate
System.arraycopy(s1, 0, s2, 0, 7); //in s1 non ci sono 7 elementi
//eccezione java.lang.ArrayIndexOutOfBoundsException
System.arraycopy(s1, 0, s2, 0, 4); //s2 ha solo 3 elementi
//eccezione java.lang.ArrayIndexOutOfBoundException
System.arraycopy(s1, 0, s2, 0, 2); //[alfa, beta, null]
Metodo gc (garbage collection)
Gli oggetti hanno un contatore dei riferimenti attivi. Quando il contatore di un oggetto scende a 0, l’oggetto
non è più accessibile (si è perso ogni riferimento). Periodicamente, in modo automatico, il runtime di java
libera la memoria della heap occupata dagli oggetti inaccessibili.
Col metodo si può chiedere esplicitamente il recupero della memoria inutilizzata. Prima della distruzione
gc
di un oggetto, è chiamato il metodo finalize, che consente di programmare il rilascio di risorse (esterne) non
trattate dal garbage collector.
Seconda parte di programmazione ad oggetti
Interfacce
Le interfacce sono tipi, quindi è possibile che un riferimento abbia come tipo un’interfaccia. Le interfacce
sono introdotte con la keyword interface. Un’interfaccia può contenere metodi astratti (senza body), metodi
“normali”, metodi statici, costanti e annidati. Un’interfaccia non è instanziabile, quindi a che cosa punta un
riferimento di tipo interfaccia? Punta ad un oggetto di una classe che implementa l’interfaccia. Se una classe
dichiara di implementare un’interfaccia (o anche più di una) deve implementare i metodi astratti.
Significato
Se due classe A e B implementano la stessa interfaccia I, un riferimento R di tipo I può puntare ad un oggetto
di tipo A o ad un oggetto di tipo B (oltre ad un oggetto derivato da A o B). I metodi applicabili a R sono quelli
definiti in I, che sono implementati sia in A che in B; si ha, quindi, un polimorfismo con classi che non
appartengono alla stessa linea di inheritance.
Interfaccia semplice
public interface Movable{
void move(int x, int y);
}
L’interfaccia Movable contiene soltanto il metodo astratto move (implicitamente e
public abstract).
//programma di test
public static voi main(String[] args){
Point p = new Point(23, 94);
Particle pa = new Particle(10, 20, 100);
Rectangle r = new Rectangle(p, 1000, 2000);
Movable m; //il riferimento m ha per tipo un’interfaccia
m = p;
m.move(1,2); //unico metodo utilizzabile
System.out.println(m); //x=1 y=2
m=r;
m.move(1,2);
System.out.println(m); //x=1 y=2 w=1000 h=2000
m=pa;
m.move(1,2);
System.out.println(m); //x=1 y=2 m=100
Movable[] a = {p, r, pa};
System.out.println(Arrays.toString(a));
//[x=1 y=2, x=1 y=2 w=1000 h=2000, x=1, y=2, m=100]
}
Attraverso le interfacce possiamo accomunare classi, cioè oggetti non imparentati. Cioè io posso associare
alla variabile m di tipo interfaccia qualsiasi oggetti che appartiene a classi in cui è definito il metodo move.
Esercizio: expression tree
Un expression tree è una struttura che rappresenta le espressioni aritmetiche senza usare le parentesi per
stabilire le precedenze. Si vuole definire una struttura e come calcolarne il risultato a partire dal nodo iniziale.
L’espressone è (10+20)*3. Abbiamo due tipi di nodi: operando o operatore. Tali classi non imparentabili,
perché si comportano in maniera nettamente diversa. Tuttavia, entrambe le
classi fanno parte dell’operazione che va risolta. Possiamo quindi definire
un’interfaccia Computable che implementi il metodo compute che tratti
l’operando o l’operatore e restituisca un risultato (polimorfismo con classi non
imparentate).
public interface Computable{
int compute();
}
In questo modo possiamo implementare la risoluzione in questo modo:
public static void main(String[] args){
Computable root = new Mult( new Add(new Operand(10), new
Operand(20)), new Operand(3));
System.out.println(root.compute()); //90
}
//CLASSI
public class Add implements Computable{
Computable left, right;
public int compute(){
return left.compute() + right.compute();
}
public Add(Computable left, Computable right){
this.left=left;
this.right=right;
}
}
public class Mult implements Computable{
COmputable left, right;
public int compute(){
return left.compute() * right.compute();
}
public Mult(Computable left, Computable right){
this.left=left;
this.right=right;
}
}
public class Operand implements Computable{
int value;
public int compute(){ return value;}
public Operand(int value){this.value=value;}
}
Se avessimo voluto implementare l’operatore unario “-“ avremmo dovuto aggiungere un’altra classe adibita
allo scopo:
public class Minus implements Computable{
Computable item = null;
public Minus (Computable item) {this.item = item;}
public int compute() {return -item.compute();}
}
//programma di test
public static void main(String[] args){
Computable root = new Minus( new Mult( new Add(new Operand(10), new
Operand(20)), new Operand(3)));
System.out.println(root.compute()); //-90
}
Riepilogo
Le interfacce non possono essere istanziate; possono essere implementate da classi o estese ad altre
interfacce. Una classe può implementare più di un’interfaccia (separate da virgole). Un’interfaccia può essere
il tipo di un riferimento; allora quel riferimento può puntare soltanto ad un oggetto la cui classe implementi
l’interfaccia. Le interfacce possono contenere anche costanti, metodi, metodi statici o tipi annidati. I metodi
sono implicitamente pubblici, le costanti sono implicitamente e
public, static final.
Metodi default
Se un’interfaccia si aggiunge un metodo default, non occorre aggiornare le classi che la implementano; è
comunque possibile farlo per ridefinire il metodo default.
Esempio
public interface Movable{
voi move(int x, int y);
int limit = 100; //costante
default boolean checkLimit(int x, int y){
return x<=limit && y<=limit;
}
Con il metodo checkLimit si controlla che le coordinate rientrino nel limite stabilito. In tal caso, restituisce
true.
Tipi generici
Sono fondamentali per costruire contenitori di oggetti di tipi non noti a priori. La struttura e la gestione di
questi contenitori è indipendente dai tipi degli oggetti contenuti.
In particolare, è una classe o un’interfaccio che dei parametri; tali parametri sono tipi non noti a priori, perciò
non indicati con lettere maiuscole (es.: T, E).
Una classe generica definisce una struttura per organizzare oggetti omogenei indipendentemente dal loro
tipo.
Esempio
public class Container <T> {…}
Per usare questa classe occorre specializzarla con un tipo non generico:
Container <String> sc;
Container <Integer> ic;
Un tipo generico semplice
Si definisca un contenitore capace di contenere un solo oggetto, che si mette con il metodo put e si toglie col
metodo take.
public class Container <T>{
private T contents = null;
public void put (T item){contents=item;} //stesso tipo di T
public T take(){T item = contents; contents = null; return item;}
}
Specializzazione per ottenere un contenitore di stringhe
Container <String> sc = new Container <String> ();
//sc opera solo su stringhe
sc.put(“alfa”);
System.out.println(sc.take()); //alfa
Il codice è scritto una volta sola nella classe generica.
Classe e interfaccia generale
Si costruisca uno stack generico, Stack <T>, le cui proprietà sono definite nell’interfaccia generica seguente;
public interface StackI <T>{
boolean put(T t);
T get();
int lenght(); //n.elementi
int getSize(); //capacità
}
Nota: a differenza del contenitore lo stack contiene più oggetti; serve una struttura dati ad es. un array di
Object. Inoltre, il costruttore dello stack permette di stabilire la sua capacità. Il metodo put da false se lo
stack è pieno e get dà null se è vuoto.
package Stack;
import java.utili.*;
public class Stack<T> implements StackI <T> {
private T[] stack;
private int size;
private int l = -1; //indice ultimo elemento (-1 = vuoto)
@SuppressWarnings(“unchecked”)
public Stack (int size) {
stack = (T[]) new Object[size];
this.size = size;
}
public boolean put (T t){<