mercoledì 10 aprile 2013

poliformismo per i metodi

overload e override

metodo public static void main(String[] args)

In ogni applicazione java ci vuole un metodo così definito :
public static void main(String[] args)
E' la dichiarazione del metodo main() che definisce il punto di partenza dell’esecuzione di ogni programma.
 

operatori logico-booleani


Operatori logico – booleani
Gli operatori booleani operano solo su operandi booleani e restituiscono un tipo booleano:

Descrizione
Operatore
NOT logico
!
AND logico
&
OR logico
|
XOR logico
^
Short circuit AND
&&
Short circuit OR
||
AND e assegnazione
 &=
OR e assegnazione
|=
XOR e assegnazione
 ^=

AND
A
B
A && B
true
true
true
true
false
false
false
true
false
false
false
false


OR
A
B
A || B
true
true
true
true
false
true
false
true
true
false
false
false

 

JAVA da linea di comando

Prendiamo una classe principale con metodo main :

public class Principale {

       public static void main(String[] args) {

             System.out.println(args[0]);

             System.out.println(args[1]);

             System.out.println(args[2]);

       }

}

 

Questa classe se compilata in un file .class può essere invocata da linea di comando :

java Principale [parametri]

Si hanno tre casi :

·       Numero parametri corretto

·       Numero parametri inferiore a quelli attesi

·       Numero parametri superiore a quelli attesi

Nel primo caso e nel terzo caso si ottiene una esecuzione corretta mentre nel secondo si ottiene una java.lang.ArrayIndexOutOfBoundsException.

 


 

martedì 9 aprile 2013

classe e oggetto

Una classe è un’astrazione indicante un insieme di oggetti che condividono le stesse caratteristiche e le stesse funzionalità.

Un oggetto è un’istanza (ovvero, una creazione fisica) di una classe.
Un membro è
  • Attributo (variabile membro) detto anche campo.
  • Metodo (metodo membro)

Il tipo di dato boolean


Il tipo di dato boolean utilizza solo un bit per memorizzare un valore e gli unici valori che può immagazzinare sono true e false.


      boolean b = true;
      boolean b = false;



Il costrutto if




if (espressione-booleana) {
     istruzione_1;
     ...........;
     istruzione_k;
     } else if (espressione-booleana){
     istruzione_k+1;
     .............;
     istruzione_j;
     } else if (espressione-booleana){
     istruzione_j+1;
     .............;
     istruzione_h;
     } else {
     istruzione_h+1;
     .............;
     istruzione_n;
     }


metodi


Nella definizione di classe col termine funzionalità ci si riferisce ai metodi che quindi rappresentano le azioni.
Dichiarazione di un metodo

[modificatori] tipo_di_ritorno nome_del_metodo ([parametri]) {corpo_del_metodo}
  • modificatori: parole chiave di Java che modificano funzionalità e caratteristiche in un metodo.
  • tipo di ritorno: il tipo di dato che un metodo potrà restituire dopo essere stato chiamato.
  • nome del metodo: identificatore del metodo.
  • parametri: dichiarazioni di variabili ingresso. Possono essere un numero qualunque e di tipo diverso. I parametri si separano con una virgola.
  • corpo del metodoL’insieme di istruzioni che verranno eseguite dal metodo.

La coppia costituita dal nome del metodo e l’eventuale lista dei
parametri viene detta “firma” (in inglese “signature”) del metodo e lo identifica in modo univoco.

A meno che non sia astratto un metodo deve per forza avere un corpo.

Chiamata di un metodo
Se la classe dove è definito un metodo nomeMetodo è la nomeOggetto la chiamata si scrive:
            nomeOggetto ogg = new nomeOggetto();
         ogg.nomeMetodo([parametri]) ;
Quando si chiama un metodo bisogna passargli tutti i parametri che sono stati dichiarati altrimenti si ottiene un errore di compilazione:
The method metodo(int) in the type nomeOggetto is not applicable for the arguments ()

Se un metodo non è void deve per forza avere un tipo di ritorno
Se un metodo è void non ha un tipo di ritorno, però può usare la parola return per uscire dal flusso logico in un certo punto del suo corpo.

ciclo for


Ciclo for
Sintassi :
             for (inizializzazione; espr. booleana; aggiornamento) {

                    istruzione_1;
                    ...........;
                    istruzione_n; }

nel caso di istruzione singola il blocco di codice è opzionale :
              for (inizializzazione; espr. booleana; aggiornamento) { istruzione;}
             for (inizializzazione; espr. booleana; aggiornamento) istruzione;

Queste tre istruzioni possono anche essere completamente indipendenti tra loro.

Le dichiarazioni vanno separate da virgole, ed hanno il vincolo di dover essere tutte dello stesso tipo (in questo caso int).

Anche gli aggiornamenti vanno separati con virgole, ma non ci sono vincoli in questo caso. In questo “settore” del for possiamo eseguire altre istruzioni, per esempio invocare metodi:

for (int i = 0, j = 10; i < 5 || j > 5; i++, j--,
             System.out.println("aggiornamento"))
                    {
                    ...
                    }

Il ciclo for migliorato o enhanced for loop è un ciclo for semplificato nella sintassi :

for (variabile_temporanea : oggetto_iterabile) {
corpo;
}

 

Costruttore di default


Se una classe non contiene nessuna dichiarazione di costruttore allora viene implicitamente dichiarato un costruttore senza parametri formali e nessuna clausola throws.

Lista completa dei modificatori in java

Tutti i modificatori applicabili ad ogni componente JAVA.

CLASSE
ATTRIBUTO
METODO
COSTRUTTORE
BLOCCO DI CODICE
public
SI
SI
SI
SI
NO
protected
NO
SI
SI
SI
NO
(default)
SI
SI
SI
SI
SI
private
NO
SI
SI
SI
NO
abstract
SI
NO
SI
NO
NO
final
SI
SI
SI
NO
NO
native
NO
NO
SI
NO
NO
static
NO
SI
SI
NO
SI
strictfp
SI
NO
SI
NO
NO
synchronized
NO
NO
SI
NO
NO
transient
NO
SI
NO
NO
NO

Eccezioni



Una eccezione è una situazione imprevista che il flusso di un’applicazione può incontrare e che può essere gestita.
Un errore è una situazione imprevista non dipendente da un errore commesso dallo sviluppatore e non può essere gestito.

Errori ed eccezioni derivano da Throwable.
Tutti gli Errori derivano da Error.
Tutte le eccezioni derivano da Exception.

Se JAVA si imbatte in un'eccezione la "lancia", interrompendo l'esecuzione e stampando a video l'errore:

public class Principale {
     public static void main(String[] args) {
         int a=1;
         int b=0;
         System.out.println(a/b);
     }
}

Exception in thread "main" java.lang.ArithmeticException: / by zero
     at Principale.main(Principale.java:5)

L’eccezione può essere gestita con un try catch :

         try {
         System.out.println(a/b);  
         }
         catch (ArithmeticException exc) {
              System.out.println("Divisione per ZERO");
         }
         }
L’eccezione dichiarata (ArithmeticException) deve essere quella giusta altrimenti il catch non la cattura.
Le eccezioni sono polimorfe e quindi si può dichiarare e catturare una eccezione superiore :
         try {
         System.out.println(a/b);  
         }
         catch (Exception exc) {
              System.out.println("eccezione generica");
         }
         }
Si possono dichiarare varie eccezioni e così discrimnare la gestione a seconda dell’eccezione catturata:
         try {
         System.out.println(a/b);  
         }
         catch (ArithmeticException exc) {
              System.out.println("Divisione per ZERO ");
         }
         catch (NullPointerException exc) {
              System.out.println("riferimento nullo");
         }
         catch (Exception exc) {
              System.out.println("eccezione generica");
         }
In questo caso l’ordine è importante, il catch che entra in azione è quello scritto per primo.

finally indica un blocco che deve essere sempre eseguito, sia se c’è una eccezione oppure no :
         try {
         System.out.println(a/b);  
         }
         catch (ArithmeticException exc) {
              System.out.println("divisione per zero");
         }
         catch (NullPointerException exc) {
              System.out.println("riferimento nullo");
         }
         catch (Exception exc) {
              System.out.println("eccezione generica");
         }
         finally { System.out.println("Tentativo di operazione"); }

Eccezione personalizzata :
public class PersonalizzataException extends Exception {
     public PersonalizzataException() {
         super("Problema personalizzato");
     }
     public String toString() {
         return getMessage() + ": messaggio personalizzato";
     }
}
si lancia in modo diretto:
public class Principale {
     public static void main(String[] args) throws PersonalizzataException {
         boolean controllo = true;      
         if (controllo){
              PersonalizzataException eccezione = new PersonalizzataException();
              throw eccezione;
         }
     }
}
Si può anche scrivere in modo compatto:  throw new PersonalizzataException();
e si ottiene:
Exception in thread "main" Problema personalizzato: messaggio personalizzato
     at Principale.main(Principale.java:5)

Perché creare eccezioni personalizzate? Consideriamo questo codice :
public class ClasseProblematica {
     public ClasseProblematica(int a) {
         try {
              metodo(a);
         } catch (PersonalizzataException e) {
              System.out.println("errore gravissimo!!!");
         }
     }
     public void metodo(int a) throws PersonalizzataException {
         if (a > 1) {
              throw new PersonalizzataException();
         }
     }

}
public class PersonalizzataException extends Exception {
     public PersonalizzataException() {
         super("Problema personalizzato");
     }
     public String toString() {
         return getMessage() + ": messaggio personalizzato";
     }
}
public class Principale {
     public static void main(String[] args) {
         for (int i = 0;i<3;i++){
              ClasseProblematica cp = new ClasseProblematica(i);
              System.out.println("tutto benissimo con "+i);
         }
        
     }
}

In questo caso pur catturando l’eccezione nel metodo il risultato non è buono perché si prosegue nell’elaborazione:
tutto benissimo con 0
tutto benissimo con 1
errore gravissimo!!!
tutto benissimo con 2
A questo punto entra in campo la forza di JAVA, consentendo la propagazione dell’eccezione; l’eccezione non deve essere catturata per forza dove si produce ma anche esternamente, consentendo una gestione molto migliore del flusso di lavoro:
public class ClasseProblematica {
     public ClasseProblematica(int a) throws PersonalizzataException{
      metodo(a);

     }
     public void metodo(int a) throws PersonalizzataException {
         if (a > 1) {
              throw new PersonalizzataException();
         }
     }

}
public class Principale {
     public static void main(String[] args) {
         for (int i = 0; i < 3; i++) {
              try {
                  ClasseProblematica cp = new ClasseProblematica(i);
                  System.out.println("tutto benissimo con " + i);
              } catch (PersonalizzataException e) {
                  System.out.println("errore gravissimo!!!");
              }
             
         }

     }
}
tutto benissimo con 0
tutto benissimo con 1
errore gravissimo!!!

Con la clausola throws nella dichiarazione del metodo, in pratica è come se avvertissimo il compilatore che siamo consapevoli che il metodo possa lanciare al runtime la PersonalizzataException, e di non “preoccuparsi”, perché gestiremo in un’altra parte del codice l’eccezione. Se un metodo “chiamante” vuole utilizzare un altro metodo “daChiamare” che dichiara con una clausola throws il possibile lancio di un certo tipo di eccezione, allora, il metodo “chiamante”, o deve gestire l’eccezione con un blocco try – catch che include la chiamata al metodo “daChiamare”, o deve dichiarare anch’esso una clausola throws alla stessa eccezione.