image/svg+xml $ $ ing$ ing$ ces$ ces$ Res Res ea ea Res->ea ou ou Res->ou r r ea->r ch ch ea->ch r->ces$ r->ch ch->$ ch->ing$ T T T->ea ou->r

Le langage Java en quelques mots

Pourquoi développer en Java ?

Les multiples facettes de Java

Les interfaces de programmations (API)

Un Hello World en Java

public class HelloWorld
{
	public static void main(String[] args)
	{
		System.out.println("Hello World !");
	}
}

Remarque :

Compilation et exécution

Sûreté du typage

Contrairement à PHP (et comme le Pascal objet), Java est un langage compilé (en bytecode) avec un système de typage fort :

int a = 7;
a = 8; // Cette affectation ne pose pas de problème
a = 8.0; // On affecte un double qui sera automatiquement converti en int
a = true; // Cette affectation est impossible, le compilateur émettra une erreur
String s = "le contenu de a est : " + a; // la concaténation entre une string et un int est possible: l'int est converti en string

Quels sont les résultats affichés ?

System.out.println("a: " + 3/2.0);
System.out.println("b: " + 3/(int)2);
System.out.println("c: " + 1 + 1.0);
System.out.println("d: " + 1 + 1);
System.out.println("e: " + (1 + 1));
System.out.println("f: " + (1 / 0));
System.out.println("g: " + (1 / 0.0));

Variables locales

Exemple : une méthode calculant la factorielle d'une nombre (cette méthode est implantée dans une classe)

public static long fact(int n)
{
	long result = 1L;
	for (int i = 2; i <= n; i++)
		result *= i; // la portée de i est limitée au bloc de la boucle for
	System.out.println(i); // cette instruction ne compile pas car i n'est plus accessible
	return result;
}

Cette méthode est équivalente :

public static long fact2(int n)
{
	long result = 1L;
	int i;
	i = 2;
	while (i <= n)
	{
		result = result * i;
		i += 1;
	}
	return result;
}

On pourrait également proposer une telle implantation :

public static long fact3(int n)
{
	return (n < 2) ? 1L : n * fact3(n-1);
}

Deux types de types

En Java, il existe deux catégories de types :

Les noms de types primitifs commencent toujours par une minuscule. Les noms de types objet doivent toujours commencer par une majuscule et adopter un nommage CamelCase (mais ce n'est qu'une convention non contraignante).

La classe Scanner

Scanner permet de lire une entrée en la découpant en unités élémentaires.

On instancie d'abord un Scanner afin de lire sur l'entrée standard de la console (mais on pourrait lire sur n'importe quel entrée telle qu'un fichier ou une socket réseau) :
Scanner s = new Scanner(System.in);
On peut ensuite récupérer un mot (s.next()), une ligne (s.nextLine()), un entier (s.nextInt()), un double (s.nextDouble())... Mais auparavant, il ne faut pas oublier d'interroger le scanner pour savoir si une telle donnée existe (s.hasNext(), s.hasNextLine(), s.hasNextInt()...).

Un petit exemple :

public class Parrot
{
	public static int listenAndRepeat(int n) throws IOException
	{
		int counter = 0;
		Scanner s = new Scanner(System.in);
		while (s.hasNextLine())
		{
			String line = s.nextLine();
			for (int i = 0; i < n; i++)
			{
				System.out.println(line);
				counter++;
			}
		}
		s.close();
		return counter;
	}
	
	public static void main(String[] args) throws IOException
	{
		int n = Integer.parseInt(args[0]);
		listenAndRepeat(n);
	}
}

La Javadoc, l'ami du développeur Java

Toute la documentation à propos des classes Java peut être trouvée dans la Javadoc. Une Javadoc est disponible pour l'API du J2SE. Il est possible également de générer la Javadoc pour ses propres programmes. Par exemple, documentons la classe Parrot :

/** A nice class to emulate a parrot 
 * repeating all the lines that are fed to him
 */
public class Parrot
{
...

/** Retrieve lines from the standard input
 * and print them n times on the standard output
 * 
 * @param n the number of times to print the lines
 * @return the number of printed lines
 */
 public static int listenAndRepeat(int n) { ... }
}

Générons la Javadoc avec le programme javadoc:
`` javadoc -d destination Parrot.java

Un premier objet

 public class Parrot
 {
 	public static final int DEFAULT_REPEAT_NUMBER = 1;
 	
 	final String name;
 	final int repeatNumber;
 	
 	public Parrot(String name, int repeatNumber)
 	{
 		this.name = name;
 		this.repeatNumber = repeatNumber;
 	}
 	
 	public Parrot()
 	{
 		this(DEFAULT_REPEAT_NUMBER);
 	}
 	
 	public void present()
 	{
 		for (int i = 0; i < repeatNumber; i++)
 			System.out.println("My name is " + name);
 	}
 	
 	public void listenAndRepeat() throws IOException { ... }
 	
 	public static void main(String[] args) throws IOException
 	{
 		Parrot p = new Parrot("Coco", Integer.parseInt(args[0]));
 		p.present();
 		p.listenAndRepeat();
 	}

Manipulation des objets par référence

public class Point
{
	final int x;
	final int y;
	
	public Point(int x, int y)
	{
		this.x = x;
		this.y = y;
	}
	
	public String toString()
	{
		return String.format("(%d,%d)", x, y);
	}
}

public class PointHandler
{
	public static void invertPoint(Point p)
	{
		Point invertedPoint = new Point(p.y, p.x);
		p = invertedPoint;
	}
	
	public static void main(String[] args)
	{
		//Point p = null;
		//System.out.println(p.x); // raise NullPointerException
		Point p = new Point(1, 2);
		System.out.println(p);
		invertPoint(p);
		System.out.println(p);
	}
}

Une bonne habitude : les getters et setters

Un petit exemple avec un point :

public class Point
{
	private int x = 0;
	private int y = 0;
	
	public int getX() 
	{
		return x;
	}
	
	public void setX(int x)
	{
		this.x = x;
	}
	
	public int getY()
	{
		return y;
	}
	
	public void setY(int y)
	{
		this.y = y;
	}
	
	public void invert()
	{
		int tmp = x;
		this.x = y;
		this.y = tmp;
	}
}

Structures de contrôle

En Java, les structures de contrôle classiques disponibles en C(++), PHP... sont utilisables :

Un exemple : calcul du n-ième terme de la suite de Fibonacci

Suite de Fibonacci ainsi définie :

public static long fib(final int n)
{
	long a = 0; // penultimate term
	long b = 1; // ultimate term
	long result;
	switch (n)
	{
		case 0: 
			result = a;
			break;
		case 1: 
			result = b;
			break;
		default:
			for (int i = 2; i <= n; i++)
			{
				final long tmp = a;
				a = b;
				b += tmp;
			}
			result = b;
	}
	return result;
}

public static long main(String[] args)
{
	int n = Integer.parseInt(args[1]); // rank to compute
	System.out.println(String.format("fib(%d)=%d", n, fib(n)));
}

Remarques :

Un petit jeu : deviner un nombre

Quelques indications pour réaliser ce jeu :

Crééons des points

Nous allons instantier plein de points aléatoires avec une fabrique de points.

public class PointFactory
{
	final Random r;
	
	public PointFactory()
	{
		this.r = new Random(); // we initialize the random number generator
	}
	
	public Point createRandomPoint()
	{
		return new Point(r.nextInt(), r.nextInt());
	}
}

Et nous écrivons maintenant une méthode main :

public class PointTester
{
	public static void main(String[] args)
	{
		PointFactory pf = new PointFactory();
		// List<Point> l = new ArrayList<Point>();
		while (true)
		{
			Point p = pf.createRandomPoint();
			// l.add(p);
		}
	}
}

Les tableaux

Un tableau est une suite finie de cellules contiguës en mémoire pouvant accueillir des éléments d'un type donné :

Quel est l'espace mémoire maximal occupé sur le tas par l'exécution du code suivant :

public class ArrayTest
{
	public static void main(String[] args)
	{
		Point[] pointArray = new Point[1000];
		Point p = new Point(0,0);
		for (int i = 0; i < pointArray.length; i++)
			pointArray[i] = p;
		p.setX(1);
		for (int i = 0; i < pointArray.length; i++)
			System.out.println(p);
	}
}

Espace mémoire occupé :

Remarques :

Utilisation d'un tableau : le crible d'Eratosthène

package fr.upem.jacosa.general;

import java.io.PrintStream;
import java.util.Arrays;

/** Implementation of the Eratosthenes's sieve to identify the first prime numbers */
public class PrimeSieve
{
	private final boolean[] primeStatus;
	
	public PrimeSieve(int n)
	{
		primeStatus = new boolean[n];
		Arrays.fill(primeStatus, true); // by default all the integers are prime... until being declared as a multiple by a sieve iteration
	}
	
	/** Mark integers that are multiple of k */
	public void mark(int k)
	{
		for (int i = 2*k; i < primeStatus.length; i += k)
			primeStatus[i] = false;
	}
	
	/** Do all the marking iterations */
	public void mark()
	{
		if (primeStatus.length >= 0) primeStatus[0] = false;
		if (primeStatus.length >= 1) primeStatus[1] = false;
		for (int i = 2; i * i < primeStatus.length; i++)
			if (primeStatus[i])
				mark(i);
	}
	
	public void printPrimes(PrintStream out)
	{
		for (int i = 0; i < primeStatus.length; i++)
			if (primeStatus[i])
				out.println(i);
	}
	
	public static void main(String[] args)
	{
		PrimeSieve ps = new PrimeSieve(Integer.parseInt(args[0]));
		ps.mark();
		ps.printPrimes(System.out);
	}
}