Paola Magillo, Univestita' di Genova, Corso di Programmazione II per SMID, a.a. 2007-2008.

Lezione 00:

IL LINGUAGGIO JAVA

In questo corso vedremo Java come caso di linguaggio di programmazione orientato a oggetti (object-oriented programming language).

Siccome la pratica e' la parte che riesce piu' difficile, quest'anno partiamo proprio da quella. Vediamo subito un esempio...

Linguaggi orientati ad oggetti (O.O. = Object-Oriented)

In un linguaggio imperativo tradizionale (non O.O.) ci sono:

Esempio: tipo rettangolo in C

Il tipo "rettangolo" e' un record con due interi per lunghezza e larghezza. La funzione "area" prende un rettangolo e ne ritorna l'area. La funzione "print" stampa un rettangolo.

#include <stdio.h>

typedef struct { int length, width; } Rectangle;

int area(Rectangle r)
{ return r.length * r.width; }

void print(Rectangle r) 
{ printf("Rettangolo %d x %d\n",r.length,r.width); }

void main()
{
  Rectangle r;
  int a;
  r.length = 3; r.width = 5;
  a = area(r);
  print(r);
  printf("Area = %d\n",a);
}

In un linguaggio object oriented:

Esempio: classe rettangolo in Java

La classe "rettangolo" ha due interi per lunghezza e larghezza, un metodo "area" che ritorna l'area del rettangolo e un metodo "print" che stampa il rettangolo.

class Rectangle
{
  int length, width;

  int area()
  { return length * width; }

  void print()
  { System.out.println("Rectangle " + length + " x " + width); }

  public static void main(String[] args)
  {
    Rectangle r = new Rectangle();
    int a;
    r.length = 3; r.width = 5;
    a = r.area();
    r.print();
    System.out.println("Area = " + a);
  }
}

Convenzione: in Java i nomi di classe hanno iniziale maiuscola, gli altri nomi iniziale minuscola. Se un nome e' fatto da piu' parole, le successive hanno iniziale maiuscola (es. "printArea").

Chiamata di metodo

Notazione analoga alla selezione di un campo di un record. Ma e' una funzione, quindi ha sempre le () e puo' avere argomenti. Es. se r e' un rettangolo:

L'oggetto su cui si chiama il metodo e' argomento privilegiato del metodo.

All'interno dell'implementazione del metodo, l'argomento privilegiato e' lasciato implicito. Es. nel metodo

  int area() { return length * width; }
si intende che length e width appartengono al rettangolo su cui sara' chiamata la funzione (r se chiamata con r.area()).

Classi e oggetti

Una classe e' l'analogo di un tipo ma comprende anche le funzioni che agiscono su quel tipo.
E' come un record dove alcuni campi sono variabili ed altri sono funzioni.

Come si dice "un valore di un tipo" cosi' si dice "un oggetto di una classe". Si dice anche che un oggetto e' istanza della sua classe.

Un oggetto ha:

Il metodo "main"

Java e' linguaggio totalmente object oriented. A parte i tipi base (int, float, double, boolean, char) tutti gli altri tipi sono classi. E tutte le funzioni appartengono a qualche classe.

Anche il "main" e' una funzione in una classe, che deve avere i seguenti parametri:

  public static void main(String[] args)
Posso "eseguire" qualsiasi classe contenga questa funzione. Quello che viene eseguito e' il main.

Come usare Java

Dal file sorgente all'esecuzione del programma

Il programmatore scrive il sorgente del programma in un linguaggio di programmazione. Tale linguaggio e' comprensibile all'uomo ma non dalla macchina.

Per poter essere eseguito dalla macchina, il sorgente deve essere tradotto nel linguaggio proprio della macchina, che e' binario e incomprensibile all'uomo.

Questa traduzione puo' avvenire in due modi:

  1. Mediante compilatore: la traduzione avviene una volta per tutte e il programma tradotto viene memorizzato in un file eseguibile.
    L'eseguibile puo' poi essere mandato in esecuzione senza bisogno di essere tradotto di nuovo e quindi senza bisogno di avere il file sorgente e il compilatore. L'esecuzione e' veloce.
    Ma funziona solo su macchine che abbiano la stessa architettura di dove e' stato compilato. Perche' l'eseguibile e' scritto nel linguaggio binario specifico di questa macchina con questo sistema operativo.

  2. Mediante interprete: la traduzione avviene al momento stesso dell'esecuzione e va ripetuta ogni volta.
    Di fatto ad essere eseguito e' l'interprete, il quale carica il file sorgente e lo esamina una istruzione alla volta, traducendo man mano la prossima istruzione che deve essere eseguita.
    Per poter eseguire il programma, ho bisogno sempre del file sorgente e dell'interprete. L'esecuzione e' lenta.
    Pero' il programma (in quanto sorgente non compilato) rimane portabile su qualsiasi architettura, purche' vi sia installato l'interprete.

Potremmo riassumere:

I progettisti di Java hanno voluto fondere i vantaggi di entrambe le tecniche (slogan di java: "compile once, execute everywhere").
Java e' linguaggio pensato per generare programmi portabili su piattaforme diverse senza essere (interamente) ri-tradotti.

  1. il sorgente e' compilato (una volta per tutte) in un formato quasi-eseguibile chiamato bytecode, che e' binario ma non dipende dall'architettura su cui e' stato compilato.
  2. il bytecode e' interpretato (ogni volta che lo si esegue) sull'architettura specifica.

In pratica

L'esecuzione e' abbastanza veloce (il grosso della traduzione e' stato gia' fatto in compilazione).
In caso di errori run-time, l'interprete riporta esattamente dove (quale funzione, quale linea...).

Distribuzioni di Java

Java e' distribuito in due diversi pacchetti:

  1. Pacchetto con entrambi compilatore ed interprete (JSDK = Java Software Development Toolkit): serve per chi scrive i programmi.
  2. Pacchetto con solo interprete (JRE = Java Runtime Environment): serve per chi li esegue soltanto.

Java e' distribuito gratuitamente in rete per solaris / windows / linux. Sito: http://java.sun.com/ (scegliere "Downloads" dalla barra in alto e "JavaSE" nel menu', a noi interessa JSDK). d

Accortezze per scrivere i sorgenti

I sorgenti java possono essere scritti con qualsiasi editor di testi. Importante: se si usa un word processor (come MS-Word) salvare in formato "solo testo", senza formattazione.

Una classe va salvata su file con stesso nome della classe ed estensione .java (es. Rectangle.java per la classe Rectangle).
Attenzione: quando si salva in formato "solo testo", l'editor potrebbe dare automaticamente estensione .txt: bisogna ricordarsi di cambiarla.

Alcuni sistemi (es. Windows) permettono di chiamare il file sorgente con un nome diverso dal nome della classe. Pero' il file bytecode generato dal compilatore porta sempre il nome della classe. Esempio:

E' fortemente consigliato chiamare Rectangle.java il sorgente che contiene la classe Rectangle!

Inoltre fare attenzione alle lettere maiuscole e minuscole nei nomi dei file. Per Windows sono indifferenti, ma non per Java.
Es. se la classe e' Rectangle e chiamo il file rectangle.java e' come se avessi usato un altro nome (genera il bytecode Rectangle.class che io tento di eseguire con java rectangle e non va).

Un programma puo' consistere di piu' classi e piu' file (un file per classe). Java rintraccia automaticamente i file che servono, purche' siano nella directory corrente.

Compilare/eseguire nei laboratori PC1 (aula 712) e PC2

La versione di Java installata in laboratorio e' la 1.4 in PC2 e 1.6 in PC1.

I sorgenti devono essere prima compilati e poi eseguiti.

  1. Per compilare digitare (nel nostro caso): javac Rectangle.java
    Occorre compilare ogni volta che il sorgente e' stato modificato.
  2. Per eseguire digitare (nel nostro caso): java Rectangle
    Si puo' eseguire piu' volte senza ricompilare se il sorgente non e' stato modificato.

Parametri da command-line

Abbiamo detto che la funzione "main" deve essere dichiarata come:

  public static void main(String[] args)

Gli argomenti della funzione "main" sono i parametri dati su command-line quando si lancia il programma.
Esempio:

java Rectangle 12 13
Nella funzione main ritrovo:
args[0] = il primo parametro = "12"
args[1] = il secondo parametro = "13"
ecc.
String e' classe predefinita Java per le stringhe di caratteri.

Usare i parametri da command-line

I parametri da command-line arrivano al "main" sempre come oggetti di tipo stringa. Ma tali stringhe possono rappresentare numeri interi o float ecc. Come ottenere dalla stringa il valore numerico?

Le classi Integer e Float contengono funzioni relative ai numeri interi e float. In Java ogni tipo base ha una corrispondente classe che contiene operazioni di utilita' per quel tipo base.

Esempio: riscriviamo il "main" della classe Rectangle per accettare da command-line le dimensioni del rettangolo:
  public static void main(String[] args)
  {
    if (args.length!=2) 
      System.out.println("Need two arguments");
    else
    {
      int l = Integer.parseInt(args[0]);
      int w = Integer.parseInt(args[1]);
      System.out.println("Read arguments " + l + " " + w);
      Rectangle r = new Rectangle();
      int a;
      r.length = l; r.width = w;
      a = r.area();
      r.print();
      System.out.println("Area = " + a);
    }
  }

Librerie Java

Java ha una grande libreria di classi predefinite (Java Foundation Classes, JFC), tra cui:

Queste classi sono divise in package. Per usare le classi contenute in un package diverso da quello di base, bisogna "importarlo".

Manuale dei package e delle classi predefinite Java disponibile in rete ( http://java.sun.com/j2se/1.4.2/docs/api/).