Java

introduction

Antoine Vernois / @avernois

Antoine Vernois

Software Craftsman

Software Anarchist

blog : https://blog.crafting-labs.fr

twitter : @avernois

et vous ?

post-it

Vous attendez quoi de cette formation ?


tour de table

  • qui êtes vous ?
  • qu'est ce que vous faites ?
  • qu'est ce que vous aimez ?
  • qu'est ce que vous aimez moins ?
  • votre expérience avec les tests et le tdd ?

détails pratiques

  • horaires
  • repas
  • pauses

Basics

Hello World!

Hello.java :

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

Compilation & bytecode

Compilation avec javac


javac Hello.java
                        
La compilation produit du bytecode Hello.class.

Le bytecode est indépendant de la plateforme.

Exécution


java Hello
                        
ou en spécifiant le classpath

java -classpath <dir> Hello
                        

Types

Statiquement typé

Une variable doit être déclaré, et son type connu, avant d'être utilisé.

int variable = 1;
                        
Il n'y a (presque) pas d'inférence de type !

types primitifs

8 types de base

  • byte
  • short
  • int
  • long
  • float
  • double
  • boolean
  • char

Ces éléments ne sont pas des objets. On les affecte directement, sans new ou appel à un constructeur.

Wrappers

Chaque primitif est encapsulé dans une classe.
  • int -> Integer
  • short -> Short
  • ...
  • char -> Character

Il est déconseillé d'utiliser new. Il est préférable de faire appel à .valueOf( ) ou parse().

Conversion


int i = 1000;
int hexa = 0x1a; // hexa = 26
int binary = 0b1111; // binary = 15

double d1 = 123.4d; 
double d1bis = 123.4; // 'd' est pas défaut, et généralement omis. 
double d2 = 1.234e2;
float f = 123.4f;
                        

Underscore dans les nombres

Pour améliorer la lisibilité des nombres, on peut y insérer des underscores.

long creditCardNumber = 1234_5678_9012_3456L;
float pi =  3.14_15F;
                        
On ne peut mettre un underscore uniquement entre 2 nombres.

Arrays


int[] intArray = new int[10]; // crée un tableau d'int de taille 10.
Integer[] integerArray = new Integer[10];

intArray[0] = 1;

String[] months = {"january", "february", "march"};
                        

Enum


public enum Month {
    JANUARY, FEBRUARY, MARCH, APRIL 
    // je ne les mets pas tous, vous avez saisi l'idée.
}                            
                        
On peut y ajouter un constructeur

public enum Month {
    JANUARY("Jan"), FEBRUARY("Feb"), MARCH("Mar"), APRIL // idem

    private String shortName;

    private Month(String shortName) {
        this.shortName = shortName;
    }

    public getShortName() {
        return shortName;
    }
}                            
                        
Usage :

Month january = Month.JANUARY;
                        

Structure de contrôle

if (else) (if)


if (boolean) {
    // do things when boolean is true
}
                        

if (boolean) {
    // do things when boolean is true
} else {
    // do things when boolean is false
}
                        

if (boolean) {
    // do things when boolean is true
} else if (anotherBoolean) {
    // do things when boolean is false and anotherBoolean is true
} else {
    //
}
                        

switch


public String monthNumberToText(Integer monthNumber) {
    String monthText;
    switch(monthNumber) {
        case 1: 
            monthText = "January";
            break;
        case 2: 
            monthText = "February";
            break;
        // handle all cases
        default:
            throw new InvalidMonthNumberException(monthNumber);
    }
}
                        
Fonctionne avec un Enum, un nombre (Integer, Byte, Short, Character) ou une String

Ternary


(i < 2) ? System.out.println("i est inférieur à 2")
        : System.out.println("i est supérieur ou égal à 2");
                        

public String stringOrEmptyString(String input)
    return (input == null) ? ""
                           : input;
                        

(do) while


while (boolean) {
    // do things
}
                        

do {
    // do things
} while (boolean)
                        

For (each)


for (int i = 0; i < 10; i++) {
    System.out.println(i);
}
                        

List chaines = ... ; 
for (String chaine: chaines) {
    System.out.println(chaine);
}
                        

Classes, méthodes, ...

Package

Les classes sont regroupés en package. Le package est défini en tête du fichier de la classe et doit se situer dans le répertoire correspondant.

package fr.craftinglabs.training.java;
                        
dans le répertoire

fr/craftinglabs/training/java;
                        

import

pour utiliser une classe d'un autre package, il faut l'importer.

package training.java;

import training.java.another.MyClass;
import java
import training.java.another2.*; // importe toutes les classes publiques du package
                        
Souvent, l'IDE s'occupe de ça pour vous :)

Classes


public class Point {
    int x; // variable d'instance
    int y;

    public Class(int x, int y) {
        this.x = x; // this se réfère à l'instance
        this.y = y;
    }

    public int getX() {
        return x; // pas de surcharge, inutile de préciser le this.
    }
}
                        

Accès


//...
static public void main() {
    Point point = new Point(1, 2); // instanciation
    System.out.println("X=" + point.getX();
}

                        

Variables et méthodes de classe

  
public class Point {
    private int x;
    private int y;
    static int maxX = 256;

    static public getMaxX() { // méthode de classe
        // dans une méthode statique, this n'existe pas. 
        // Il est impossible d'accéder à this.x ou this.y.
        return maxX;
    }
}
                        

Accès


//...
static public void main() {
    Point.getMaxX(); // pas besoin d'instancier
}

                        

Constructeurs

                        
 public class Point {
    int x;
    int y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public Point() { // plusieurs constructeurs
        this(0, 0); // appel à un autre constructeur
    }
}
                        
Si aucun constructeur n'est spécifié, le compilateur en créera un d'office sans paramètre. Les variables d'instances seront iniatilisé avec des valeurs par défaut. C'est souvent une mauvaise idée.

Déstructeurs

Il n'y en a pas vraiment. C'est le Garbage Collector qui s'occupe de libérer la mémoire lorsque les instances ne sont plus accessibles.

Modifieurs d'accès

classes

  • public : accessible par tout le monde
  • no modifier : accessible depuis la classe, le package

méthodes et variables

  • public : accessible par tout le monde
  • protected : accessible depuis la classe, le package et les sous-classes
  • private : accessible uniquement depuis la classe
  • no modifier : à la même visibilité que la classe

Inner / nested classes

Cercle.java :

public class Circle {
    private Point center = new Point(1, 2);
    private int diameter;

    class Point { // le modifier public n'est pas possible
        // définition de la classe, variable, constructeur...
        // On est dans Cercle, donc on a accès à diameter et center
    }
}

class AnotherPoint { // déclarée dans le même fichier
    // cela reste une classe indépendante, 
    // elle n'a pas accès aux éléments private de Cercle
    // elle ne peux pas être public
}
                        

Héritage

extends


public class Circle extends Shape {
    private int radius;
    private Point center;

    public Circle(Point center, int radius) {
        super(); // appelle constructeur de la classe parente
        this.radius = radius; // les éléments spécifiques
        this.center = center;
    }

    @Override // surcharge une méthode présente dans la classe parente
    public float surface() {
        return Math.PI * Math.square(radius);
    }
}
                        

Pas d'héritage multiple.

La classe fille a accès aux méthodes et variables public et protected de la classe mère.

Les constructeurs doivent être surchargés.

final

Une méthode avec le modifier final ne peut pas être surchargées dans une sous-classe.

Classe abstraite


abstract public class Shape {
    
    abstract public float surface(); // méthode sans implémentation
}
                        

Une classe abstraite ne peut pas être instancier.

Elle peut contenir des méthodes abstraites, sans implémentation, qui devront être définié par les sous-classes.

Les interfaces


interface Perimeter {
    float perimeter();
}
                        

public class Square implements Perimeter {
    public float perimeter () {
        return sideSize * 4;
    }
}
                        

L'interface sépare le contrat de l'implémentation.

Une classe peut implémenter plusieurs interface.

L'interface peut contenir des constantes (final static) de classes. À utiliser avec prudence.

Exceptions

récuperation


public void myMethod() {
    try {
        doRiskyThings();
    } catch (AnException e) {
        doSomething();
    } catch (AnotherOne e) {
        e.printStackTrace();
    } finally {
        // peu importe ce qui c'est passé, on passera par là.
    }   
}
                        

Si une exception n'est pas rattrapée, elle est propagée le long de la chaîne d'appel. Jusqu'à tomber dans un catch ou arrêter le programme.

checked / unchecked

  • Error : les problèmes de systèmes environnement. OutOfMemoryError, VirtualMachineError
  • RuntimeException (aka unchecked exceptions) : erreur de programmation NullPointerException
  • checked exceptions : tout le reste. Elles doivent être rattrappées.

checked / unchecked

Une méthode doit déclarer les checked exceptions qu'elle peut lever :

public void myMethod() throws MyCheckedException {
    // do something
    if(somethingWrongHappened) {
        throw new MyCheckedException();
    }
}
                        
Un appelant de cette méthode a l'obligation de la catcher ou de déclarer à son tour qu'il peut la lever (catch ou throws)

Généricité

intérêt

Éviter des casts hasardeux et permettre au compilateur de vérifier les types correctement.

List list = new ArrayList();
list.add("hello");
String s = (String) list.get(0); // caster, c'est toujours risqué.
list.add(1); // compile sans problème
                        

List<String> list = new ArrayList<>();
list.add("hello");
String s = list.get(0);
list.add(1); // ne compile pas ! 1 n'est pas une string
                        

code générique


public class Pair<K, V> {
    private K key;
    private V value;
    public Pair(K key, V value) {
        this.key = key;
        this.value = value;
    }

    public K getKey() {
        return key;
    }
}
                        

Pair<Integer, String> pair = new Pair<Integer, String>(1, "1");
Pair<Integer, String> diamondPair 
                = new Pair<>(1, "1"); // depuis java 7.
                        

JPA

& hibertnate

Mémoire

& garbage collection

Threads