Couverture de code java

La couverture de code (en anglais code coverage) est une mesure utilisée en génie logiciel pour décrire le taux de code source testé d'un programme. Ceci permet de mesurer la qualité des tests effectués.

Car plus un programme est bien testé, moins il est soumis aux bugs.


La mesure de ce taux implique souvent l'utilisation de tests unitaires.


Il y a de nombreuses méthodes pour mesurer la couverture de code, Les principales sont :
  • Couverture des fonctions (Function coverage) - Chaque fonction dans le programme ont-elles été appelée?
  • Couverture des instructions (Statement Coverage) - Chaque ligne du code a-t-elle été exécutée et vérifiée ?
  • Couverture des points de tests (Condition Coverage) - Chaque point d'évaluation (tel que le test d'une variable) a-t-il été exécuté et vérifié ? (Le point de test teste-t-il ce qu'il faut ?)
  • Couverture des chemins d'exécution (Path Coverage) - Chaque parcours possible (par exemple les 2 cas vrai et faux d'un test) a-t-il été exécuté et vérifié ?
Certaines méthodes sont liées, par exemple :
La couverture des chemins implique à la fois la couverture des instructions et la couverture des points de tests.
La couverture des instructions n'implique pas la couverture des points de tests.


Pour mieux comprendre les choses, je vais monter la différence entre Couverture des instructions (Statement Coverage), Couverture des points de tests (Branch Coverage) et Couverture des chemins d'exécution(Path Coverage).

Pour cela on va utiliser le bout de code suivant:

public int returnInput(int input, boolean condition1, boolean condition2, boolean condition3) {
  int x = input;
  int y = 0;
  if (condition1) 
    x++;
  if (condition2) 
    x--;
  if (condition3) 
    y=x;
  return y;
}

Couverture des instructions

Afin d'exécuter toutes les instructions, nous devons faire seulement un seul cas de test qui fixerait toutes les conditions à vrai, dans ce cas chaque ligne du code (déclaration) va être touché. 

shouldReturnInput(8, true, true, true) - 100% instructions couvertes.

Mais seulement la moitié des branches sont couvertes et un seul chemin.

Couverture des points de tests

Vous pouvez visualiser que chaque bloc de test "if" contient deux branches (une branche vrai et une autre fausse). Ainsi, il apparaît clairement que le cas de test ci-dessus suit seulement la branche vraie de chaque "if". Donc dans ce cas seulement 50% des branches sont couvertes. 

Afin de couvrir 100% des branches, nous aurions besoin d'ajouter le cas de test suivant: 
shouldReturnInput(8, false, false, false) Avec ces deux cas de test que nous avons fait maintenant on aura 100% des branches couvertes

Couverture des chemins d'exécution

Néanmoins, il y a encore un concept de couverture de chemin. Afin de comprendre la couverture de chemin, c'est mieux de visualiser le code ci-dessus sous la forme d'un arbre binaire:



Comme vous le voyez probablement les deux cas de test ci-dessus ne concernent que deux chemins (true, true , true) et (false, false, fasle) alors qu'en fait il y a 8 chemins distinctes:

t => true
f => false

t -t -t - couvert avec le cas de test 1
t -t -f
t -f -t
t -f -f
f -t -t
f -t -f
f -f -t
f -f -f - couvert avec le cas de test 2

Donc pour que vous auriez une couverture de chemins à 100% vous devrez remplir tous les cas possible.

HTML5 : structure globale du document



Pour débuter sereinement avec une nouvelle intégration HTML5 et comprendre ses implications, nous allons commencer par le début : la structure globale d'un document.

La conception d'une page web en suivant la philosophie du standard HTML5 spécifié par le W3C (ou du standard vivant tel que désigné par le WhatWG) répond à quelques réflexes de base. La structure d'un document (l'imbrication des balises à la racine) est simplfiiée pour répondre aux attentes pragmatiques des intégrateurs et webdesigners.


Un document HTML5 minimal
Sans surprise, les bases d'un code HTML5 ressemblent beaucoup à celles rédigées à l'aide des précédentes versions HTML 4 et XHTML 1.x. Rétro-compatibilité oblige. On y retrouve donc un doctype suivi des éléments les plus courants : <html>,<head>, <title>, <meta>, <link>, <script> et <body>.
<!doctype html>
<html lang="fr">
<head>
  <meta charset="utf-8">
  <title>Titre de la page</title>
  <link rel="stylesheet" href="style.css">
  <script src="script.js"></script>
</head>
<body>
  ...
  <!-- Le reste du contenu -->
  ...
</body>
</html>
Le doctype
La première ligne d'en-tête a été considérablement simplifiée. On peut maintenant retenir un doctype par coeur, sans avoir à le copier-coller.
<!doctype html>
Ce doctype allégé a été mûrement testé et réfléchi : il permet toujours - pour les anciens navigateurs - de rester dans le mode d'interprétation conforme aux standards et d'éviter le mode quirks. On peut remarquer qu'il n'y a pas d'allusion à un quelconque numéro de version. Son rôle est toujours de préciser quel est le type de document qui va suivre, afin de permettre au navigateur de savoir quel langage de la vaste famille SGML il devra interpréter.
L'élément racine <html>
C'est lui qui va recueillir les deux principaux éléments de la hiérarchie : <head> et<body>.

L'attribut lang (sur <html>)

On a tendance à l'oublier : l'attribut lang précise la langue utilisée pour le contenu de la page, lorsqu'il est placé sur la racine <html>.
<html lang="fr">
Une langue bien indiquée sera utile ainsi aux synthèses vocales (pour adopter le bon accent).

Les fameux <head> et <body>

À ce niveau, le code HTML peut être divisé en deux parties : l'en-tête située entre les balises <head> et </head>, qui regroupe toutes les méta-informations, c'est-à-dire les données qui ne sont pas représentées directement à l'écran dans le rendu du document, mais qui lui sont tout de même liées : le titre dans <title> (extrêmement recommandé), les autres méta-informations variées (facultatives : mots-clés, description générale de la page) dans zéro ou plusieurs <meta>, et éventuellement<link><script> ou <style>.
La deuxième partie comprend le corps à proprement parler, c'est-à-dire <body>. On y retrouvera tout le reste du contenu HTML, structuré par des balises variées - selon ce que l'on aura à y placer - et dont l'apparence sera affectée par les styles CSS chargés dans <link> et/ou <style>.
L'attribut charset (sur <meta>)
Préciser l'encodage des caractères est primordial pour exploiter la bonne page de code et ne pas se retrouver avec les caractères spéciaux ou accentués. Le choix de l'UTF-8 est désormais préconisé par le W3C pour tous les protocoles échangeant du texte sur internet (dont HTML).
<meta charset="utf-8">
On retrouvera donc très souvent ce codage de caractères, par contre il faut toujours veiller à ce que l'éditeur permettant de coder en HTML (que ce soit un IDE tout-en-un ou un simple éditeur de texte) enregistre le fichier avec le bon encodage, et non en Latin-1 (alias ISO-5589-1) ou ANSI si la balise <meta> indique UTF-8.

Veillez à toujours placer cette déclaration d'encodage avant toutes les autres balises contenues dans la section
<head>. En effet, celles-ci sont immédiatement concernées, par exemple <title> qui peut déjà faire appel à des caractères en UTF-8 ; ceci également dans un but de sécuriser l'interprétation des caractères spéciaux et prévenir les injections de contenu indésirables.
L'élément <link>
Dans la majorité des cas, une balise <link> placée dans l'en-tête permet de mettre en relation la page avec d'autres documents externes. La plupart du temps cela concerne les feuilles de style CSS externes avec une relation du type stylesheet, mais il est aussi possible de définir d'autres types de relations (par exemple avec authoriconprefetchnextprev, etc).
<link rel="stylesheet" href="style.css">
En HTML5, il n'est plus strictement obligatoire de spécifier l'attribut type.

Pour inclure directement des instructions CSS dans le document HTML sans passer par un fichier externe,
<style> est à votre service. Cependant, il vaut mieux faire confiance à un fichier indépendant : il n'y aura qu'un seul code à maintenir pour de multiples pages (voire pour tout le site), et la mise en cache par le navigateur n'en sera que plus efficace.
L'élément <script>
Cet élément permet d'ajouter des scripts (JavaScript) qui vont s'éxécuter côté client dans le navigateur dès leur chargement.
<script src="script.js"></script>  
En HTML5, il n'est plus obligatoire de spécifier l'attribut type. Celui-ci est de toute manière interprété par défaut en text/javascript par tous les navigateurs.
Les autres éléments HTML5
Une fois la structure de base préparée, il est temps de commencer à y placer d'autres éléments HTML pour le contenu à proprement parler : paragraphes, listes, liens, images, vidéos, tableaux de données, formulaires, etc. La majorité des éléments HTML sont toujours au rendez-vous dans HTML5, qui se voit complété par quelques nouveautés pour le balisage. Par exemple :
    Éléments de section <section>, <article>, <header>, <footer>, <nav> et <aside>
  • Élément <datalist>
  • Éléments <details> & <summary>
  • Éléments <figure> & <figcaption>
  • Éléments média <audio> et <video> complétés par <source>
  • Élément <canvas>
  • Éléments <meter><output> et <progress>
  • Élément <time> et <mark>
  • Et tous les autres, que l'on peut retrouver dans une liste complète maintenue par le W3C : HTML : The Markup Language
Pour rappel, tous les nouveaux éléments HTML5 ne sont pas nécessairement reconnus de façon native et cohérente par tous les navigateurs (même les plus récents). Pour certains, il sera possible de trouver des alternatives avec des compléments en JavaScript. Pour d'autres, il faudra patienter jusqu'à une implémentation totale, et évaluer le risque selon le besoin : un nouvel élément sera-t-il tout de même consultable, masqué, ou géré de façon erronée ?
Pour juger de l'état de la prise en charge par les navigateurs, fiez-vous à Caniuse.com qui dresse des tableaux de support complets, ou bien encore à HTML5Please, qui indique de façon rationnelle par rapport aux parts de marché ce qu'il est possible d'utiliser en production pour un maximum de visiteurs.

java-simpledateformat-exemples



Aujourd'hui, je veux vous montrer quelques exemples de la façon dont vous pouvez utiliser la classe SimpleDateFormat dans votre code. J'espère que certains d'entre eux seront de nouveau et surprenant!
L'exemple de base :
La première utilisation la plus basique de la classe, permet de formater l'objet Date en une chaîne simple montrant jour, le mois et l'année:
1:
2:
3:
4:
5:
6:
SimpleDateFormat simpleDateFormat =
        new SimpleDateFormat("dd/MM/yy");
String dateAsString = simpleDateFormat.format(new Date());

System.out.println(dateAsString);
// Resulat: "12/11/09"
Un peu plus avancé :Évidemment, nous pouvons utiliser des format de date plus compliqués que celui là (voir SimpleDateFormat JavaDoc pour la liste complète). Nous pouvons aussi ajouter un peu de texte normal pour l'afficher avec la date, pour faire celà vous devez échapper le texte avec une apostrophe. Voici donc une façon élégante de l'impression de la date et l'heure:
1:
2:
3:
4:
5:
6:
SimpleDateFormat simpleDateFormat =
        new SimpleDateFormat("hh:mm 'o''clock on' MMMM dd yyyy");
String dateAsString = simpleDateFormat.format(new Date());

System.out.println(dateAsString);
// Result: "06:49 o'clock on November 12 2009"
Maintenant, avec Locale :
SimpleDateFormat dépend aussi du local, en offrant un Locale, vous pouvez obtenir la chaîne de la date localisée pour une langue ou un pays spécifique. Voici la date en français:
1:
2:
3:
4:
5:
6:
SimpleDateFormat simpleDateFormat =
        new SimpleDateFormat("dd MMMM yyyy zzzz G", Locale.FRENCH);
String dateAsString = simpleDateFormat.format(new Date());

System.out.println(dateAsString);
// Result: "12 novembre 2009 Heure du méridien de Greenwich ap. J.-C."
Parse String en Date :
Autre bonne chose sur la classe SimpleDateFormat c'est qu'il peut être utilisé non seulement pour la mise en forme, mais aussi pour convertir un String en Objet Date. Dans cet exemple, le format utilisé est exactement le même que celui retourné par la méthode Date.toString(). Dans cet exemple , nous allons essayer de convertir les chaînes créées par Data.toString() de nouveau en dates:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
// SimpleDateFormat that works exactly like Date.toString()
SimpleDateFormat simpleDateFormat =
        new SimpleDateFormat("E MMM dd HH:mm:ss zzz yyyy", Locale.ROOT);
Date today = new Date();

String dateAsString_format = simpleDateFormat.format(today);
String dateAsString_native = today.toString();
// Both strings are: "Thu Nov 12 18:49:36 GMT 2009"

Date parsedDate = simpleDateFormat.parse(dateAsString_native);
System.out.println(parsedDate.toString());
// Result: "Thu Nov 12 18:49:36 GMT 2009"
Changement du fuseau horaire par défaut :
Notez que lorsque vous convertissez une chaîne de caracteres en date, le résultat peut être ambiguë. Par exemple, la chaîne de caracteres "11h23 1 janvier 2001" est un moment différent selon où vous habitez, au Japon ou au Canada. Par défaut Java résout ce problème en utilisant votre fuseau horaire local obtenu à partir de la Locale par défaut. 

alors que le fuseau horaire ne peut pas être une partie de la chaîne de caracteres, vous pouvez le configurer manuellement au lieu d'utiliser l'un par défaut. Vous pouvez le faire avec la méthode settimezone():
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
SimpleDateFormat simpleDateFormat =
        new SimpleDateFormat("dd-MM-yyyy", Locale.ENGLISH);
Date date = simpleDateFormat.parse("13-07-1999");
System.out.println(date);
// Result: "Tue Jul 13 00:00:00 GMT 1999"

simpleDateFormat.setTimeZone(TimeZone.getTimeZone("PST"));
date = simpleDateFormat.parse("13-07-1999");
System.out.println(date);
// Result: "Tue Jul 13 08:00:00 GMT 1999"
Changement du siècle :
Ambiguïté similaire se produit lors de l'analyse des dates de l'année à deux chiffres. Par exemple "01/01/59" est le jour de la nouvelle année  1959 ou 2059. Cela peut être réglée en spécifiant le siècle à l'objet SimpleDateFormat, pour être plus précis avec set2DigitYearStart () méthode, vous pouvez spécifier la période de 100 ans dans lequel la date analysée sera placé. Par défaut, la période de 100 ans est [aujourd'hui - 80 ans, aujourd'hui + 20 années]. Voir l'exemple:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
SimpleDateFormat simpleDateFormat =
        new SimpleDateFormat("dd MMMM yy", Locale.ENGLISH);
Date date = simpleDateFormat.parse("1 November 45");
System.out.println(date);
// By default the year 45 will be taken from period (current year 2009) 1929 - 2029
// Result: "Thu Nov 01 00:00:00 GMT 1945"

Date startOf19thCentury = new GregorianCalendar(1801,1,1).getTime();
Date startOf21stCentury = new GregorianCalendar(2001,1,1).getTime();

simpleDateFormat.set2DigitYearStart(startOf19thCentury);
date = simpleDateFormat.parse("1 November 45");
System.out.println(date);
// After invoking set2DigitYearStart() the period is now 1801 - 1901
// Result: "Thu Nov 01 00:00:00 GMT 1845"

simpleDateFormat.set2DigitYearStart(startOf21stCentury);
date = simpleDateFormat.parse("1 November 45");
System.out.println(date);
// This time the period is 2001 - 2101
// Result: "Thu Nov 01 00:00:00 GMT 2045"
Rendre le parsing plus stricte :
Par défaut, la méthode de parsing de SimpleDateFormat est très indulgent. Si la chaîne fournie n'est pas entièrement compatible avec le format fournit, SimpleDateFormat au lieu d'abandonner essais avec beaucoup des heuristiques difficiles à deviner quelle serait la bonne réponse. Dans de nombreuses situations ce comportement est trés souhaitable, mais si vous n'aimez pas cela, vous pouvez le désactiver. Avec la méthode setLenient (), vous pouvez faire un parsing obéissent exactement le format donnée et lève une exception si la chaîne n'est pas valide. 
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
SimpleDateFormat simpleDateFormat =
        new SimpleDateFormat("dd MMMM yyyy", Locale.ENGLISH);
Date date = simpleDateFormat.parse("31 April 1999");
System.out.println(date);
// Since April has only 30 days the parser will assume
// user meant April 30th + one day = May 1st
// Result: "Sat May 01 00:00:00 GMT 1999"

// Make the parsing more strict
simpleDateFormat.setLenient(false);
// This throws java.text.ParseException: Unparseable date: "31 April 1999"
date = simpleDateFormat.parse("31 April 1999");

Java : Premier programme



Java est un langage typé et orienté objet. Il est compilé et basé sur une architecture logicielle très particulière nécessitant une machine virtuelle Java. Il utilise les notions usuelles de la programmation orientée objet : la notion de classe, d'encapsulation, d'héritage, d'interface, de virtualité, de généricité, … Il est accompagné d'un ensemble énorme de bibliothèques standard couvrant de très nombreux domaines, notamment des bibliothèques graphiques. C'est un langage qui présente d'excellentes propriétés de portabilité du code. Son gros point faible est une relative lenteur, surtout si on le compare à des langages comme le C++. Cependant, ce défaut a été résolu en grande partie par l'introduction de la technologie JIT (compilateurJust-In-Time, en anglais « juste à temps »), qui compile le code à la première exécution, permettant une exécution quasiment aussi rapide qu'en C/C++.

Voici l'exemple d'un premier programme en Java : 

Le fichier source :

Ce programme doit être écrit dans le fichier Exemple.java.
public class Exemple {
        public static void main(String[] args) {
                System.out.println("Hello world!");
        }
}

Explications sur le langage :

Ce programme est le classique Hello world. Comme son nom l'indique, ce programme va afficher la phrase "Hello world" à l'écran. Analysons-le ligne par ligne :
public class Exemple {


Cette ligne déclare une classe publique que nous appelons Exemple.
Un fichier .java ne peut contenir qu'une seule classe publique et le fichier doit porter le nom de cette classe. Ainsi, le fichier de ce premier exemple s'appellera obligatoirement Exemple.java (en respectant la casse).
Ce système de nommage permet au compilateur et à l'interpréteur de trouver les fichiers correspondant à une classe.

public static void main(String[] args) {
Cette ligne déclare une méthode appelée main. Cette méthode est le point d'entrée du programme (la méthode appelée lorsqu'il sera exécuté).
Elle prend en argument un tableau de chaînes de caractères (String[] args) et ne retourne rien (void).
Cette méthode est publique et statique, ce qui sera expliqué plus loin.
System.out.println("Hello world!");
Cette dernière instruction invoque la méthode println de l'objet out se trouvant dans la classe System en lui passant en argument la chaîne Hello world!. L'exécution de cette méthode aura pour résultat l'affichage de Hello world!.
Cette ligne peut sembler obscure pour l'instant. Les détails seront abordés par la suite.

Compilation du fichier source :

Nous allons présenter la compilation de notre programme en utilisant le compilateur gratuit Java très répandu nommé Javac, disponible gratuitement auprès d'Oracle. Cependant, il faut savoir qu'il existe aussi de nombreux environnements de développement Java permettant de taper, compiler, exécuter ou débuguer des programmes dans ce langage.
Tapez le programme précédent et sauvegardez le dans un fichier Exemple.java (pour la raison expliquée précédemment) et tapez dans une fenêtre :
Invite de commande DOSTerminal Unix
> javac Exemple.java
> dir
Exemple.class
Exemple.java
>
$ javac Exemple.java
$ ls
Exemple.class
Exemple.java
$
Le compilateur Javac a produit le fichier Exemple.class, contenant le code intermédiaire. Ce fichier n'est normalement pas éditable, ce qui peut garantir le copyright.
En cas de problèmes...
Voici les points à vérifier selon le type de problème :
Le système indique que le compilateur est introuvable 
  1. Vérifiez que vous avez installé un kit de développement Java (le JDK) et pas simplement un environnement d'exécution (JRE) qui ne comporte pas les outils de compilation.
  2. Vérifiez que le chemin du répertoire bin contenant le compilateur javac (javac.exe sous Windows) est dans la liste de la variable d'environnement PATH.
Le compilateur se lance mais affiche une erreur de classe non trouvée 
  1. Si la classe ne déclare aucun paquetage (package), vérifiez que vous lancez la commande depuis le répertoire où se trouve le fichier source (*.java). Changez de répertoire si nécessaire avant de recommencer.
  2. Sinon, vous devez lancer la commande depuis le répertoire parent du paquetage racine, en donnant le chemin relatif du fichier source depuis ce répertoire parent.
  3. Dans les deux cas ci-dessus, en plus de changer de répertoire courant, il peut être nécessaire d'ajouter le chemin de ce répertoire dans le classpath. Cela peut être fait soit dans la ligne de commande avec l'option -classpath (ou -cp), soit dans la variable d'environnement CLASS_PATH.
Le compilateur se lance mais affiche une erreur de syntaxe 
  1. Vérifiez le contenu du fichier source. Pour compiler les exemples de ce livre, le mieux est de faire un copier-coller complet du code.
  2. Assurez-vous de compiler le bon fichier source et pas un autre.

Exécution du programme :

Java est une machine virtuelle java fournie par Oracle et disponible pour de nombreux environnements.
Pour exécuter notre code intermédiaire, il faut taper :
java Exemple
L'exécution du programme affiche dans une fenêtre console la fameuse phrase Hello world!.
En cas de problèmes...
Voici les points à vérifier selon le type de problème :
Le système indique que la commande java est introuvable 
  1. Vérifiez que vous avez installé un kit de développement Java (le JDK).
  2. Vérifiez que le chemin du répertoire bin contenant l'interpréteur java (java.exe sous Windows) est dans la liste de la variable d'environnement PATH.
L'interpréteur se lance mais affiche une erreur de classe non trouvée 
  1. Vérifiez que vous avez compilé le fichier source *.java (voir section précédente) sans erreur, c'est-à-dire que vous avez obtenu un fichier compilé *.class.
  2. Si la classe ne déclare aucun paquetage (package), vérifiez que vous lancez la commande depuis le répertoire où se trouve le fichier compilé (*.class). Changez de répertoire si nécessaire avant de recommencer.
  3. Sinon, vous devez lancer la commande depuis le répertoire parent du paquetage racine, en donnant le nom complet de la classe (incluant le nom du paquetage).
  4. Dans les deux cas ci-dessus, en plus de changer de répertoire courant, il peut être nécessaire d'ajouter le chemin de ce répertoire dans le classpath. Cela peut être fait soit dans la ligne de commande avec l'option -classpath (ou -cp), soit dans la variable d'environnement CLASS_PATH.
L'interpréteur se lance mais rien ne s'affiche, ou le comportement n'est pas le même 
  1. Vérifiez le contenu du fichier source. Pour compiler les exemples de ce livre, le mieux est de faire un copier-coller complet du code.
  2. Assurez-vous de lancer la bonne classe principale et pas une autre.

Nouveautés de Java 8

TechEmpower, une entreprise de développement d'applications personnalisées basée à El Segundo, Californie, a posté une entrée de blog intitulée "Tout sur Java 8". Le billet de blog est un résumé complet des changements impactant les développeurs qui viennent avec Java 8. Voici une rapide vue d'ensemble du billet. Veuillez vous rendre sur le blog de TechEmpower pour les détails complets.
Améliorations sur les Interfaces :
Les interfaces peuvent désormais définir des méthodes statiques. Par exemple, java.util.Comparator a désormais une méthode statique naturalOrder.
    public static <T extends Comparable<? super T>> Comparator<T> naturalOrder() {
        return (Comparator<T>) Comparators.NaturalOrderComparator.INSTANCE;
    }
Les interfaces peuvent désormais fournir des méthodes par défaut. Cela permet aux développeurs d'ajouter de nouvelles méthodes sans casser le code existant implémentant l'interface. Par exemple, java.lang.Iterable a maintenant une méthode forEach par défaut.
    public default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }
    }
Notez qu'une interface ne peut pas fournir d'implémentation par défaut pour toute les méthodes de la classe Object.
Interfaces Fonctionnelles :
Une interface fonctionnelle est une interface qui défini exactement une méthode abstraite.L'annotation FunctionalInterface a été introduite pour indiquer qu'une interface est conçue comme interface fonctionnelle. Par exemple, java.lang.Runnable est une interface fonctionnelle.
    @FunctionalInterface
    public interface Runnable {
        public abstract void run();
    }
Notez que le compilateur Java considérera toute interface répondant à la définition comme interface fonctionnelle, que l'annotation FunctionalInterface soit présente ou non.

Lambdas :

La propriété importante des interfaces fonctionnelles est qu'elles peuvent être instanciées en utilisant des lambdas. Les expression lambda vous permettent de traiter une fonctionnalité comme argument de méthode, ou du code en tant que donnée.

Voici quelque
s exemples de lambdas. Les entrées sont sur la gauche et le code est sur la droite. Les types d'entrée peuvent être inférés et sont optionnels.
(int x, int y) -> { return x + y; }

(x, y) -> x + y

x -> x * x

() -> x

x -> { System.out.println(x); }
Voici un exemple d'instanciation de l'interface fonctionnelle Runnable.
    Runnable r = () -> { System.out.println("Running!"); }

Références de Méthodes :

Les références de méthodes sont des expressions lambda compactes pour des méthodes ayant déjà un nom. Voici quelques exemples de références de méthodes, avec l'expression lambda équivalente à droite.
    String::valueOf     x -> String.valueOf(x)
    Object::toString    x -> x.toString()
    x::toString         () -> x.toString()
    ArrayList::new      () -> new ArrayList<>()

Lambdas capturantes vs non-capturantes :

Les lambdas sont dites "capturantes" si elles accèdent à une variable ou un objet non statique qui a été défini hors du corps de la lambda. Par exemple, cette lambda accède à la variable x :
int x = 5;
return y -> x + y;
Une expression lambda peut seulement accéder aux variables locales et aux paramètres du bloc conteneur qui sont final ou finales dans les faits (NdT: une variable sans le mot clé final, mais instanciée une seule fois).

java.util.function :

Un grand nombre de nouvelles interfaces fonctionnelles ont été ajoutées au package java.util.function. Voici quelques exemples:
  • Function - prend un T en entrée, retourne un R en sortie 
  • Predicate - prend un T en entrée, retourne un booléen en sortie 
  • Consumer - prend un T en entrée, ne retourne rien 
  • Supplier - ne prend rien en entrée, retourne un T en sortie 
  • BinaryOperator - prend deux T en entrée, retourne un unique T en sortie.
java.util.stream :
Le nouveau package java.util.stream fourni des classes pour supporter des opérations de style fonctionnel sur des flux de valeurs. Une manière commune d'obtenir un stream sera depuis une collection :
    Stream<T> stream = collection.stream();
Voici un exemple provenant de la Javadocs du package.
    int sumOfWeights = blocks.stream().filter(b -> b.getColor() == RED)
                                      .mapToInt(b -> b.getWeight())
                                      .sum();
Ici nous utilisons une Collection de blocs comme source pour un stream, et nous réalisons une opération dite de filter-map-reduce (filtrer-transformer-réduire) pour obtenir la somme des poids des blocs rouges. Les Streams peuvent être infinis et avec état. Ils peuvent être séquentiels ou parallèles. Quand vous travaillez avec des streams, vous obtenez tout d'abord un stream depuis une source, réalisez une ou plusieurs opérations intermédiaires puis une unique opération finale de terminaison.

Les opérations intermédiaires incluent f
ilter, map, flatMap, peel, distinct, sorted, limit, et substream.

Les opérations de terminaison incluent forEach, toArray, reduce, collect, min, max, count, anyMatch, allMatch,

noneMatch, findFirst, et findAny. Une classe utilitaire très pratique est java.util.stream.Collectors. Celle-ci implémente des opérations de réduction variées, telles que convertir des streams en collections, ou l'agrégation d'éléments.

Amélioration de l'inférence des types génériques:

Ceci améliore la capacité du compilateur Java à inférer les types génériques et réduit le nombre d'arguments de typage dans les appels de méthodes génériques. En Java 7, le code ressemble à quelque-chose comme çà :
    foo(Utility.<Type>bar());
    Utility.<Type>foo().bar();
En Java 8, l'inférence améliorée dans les arguments et appels chaînés vous permet d'écrire quelque-chose comme çà:
    foo(Utility.bar());
    Utility.foo().bar();

java.time :

La nouvelle API date/heure est contenue dans le package java.time. Toutes les classes sont immuables et thread-safe. Les types date et heure incluent Instant, LocalDate, LocalTime, LocalDateTime et ZonedDateTime. Au delà des dates et des heures, il y a aussi les types Duration (durée) et Period (périodicité).

D'autres types de valeurs incluent Month, DayOfWeek, Year, Month, YearMonth, MonthDay, OffsetTime et OffsetDateTime. La plupart de ces nouvelles classes de date/heure sont supportées par JDBC.

Ajouts à l'API Collections :

La capacité des interfaces à avoir des méthodes par défaut a permis à Java 8 d'ajouter un grand nombre de nouvelles méthodes à l'API Collections. Les implémentations par défaut ont été fournies sur toutes les interfaces et des implémentations plus efficaces ont été ajoutées aux classes concrètes quand cela était possible. Voici une liste des nouvelles méthodes :
  • Iterable.forEach(Consumer)
  • Iterator.forEachRemaining(Consumer)
  • Collection.removeIf(Predicate)
  • Collection.spliterator()
  • Collection.stream()
  • Collection.parallelStream()
  • List.sort(Comparator)
  • List.replaceAll(UnaryOperator)
  • Map.forEach(BiConsumer)
  • Map.replaceAll(BiFunction)
  • Map.putIfAbsent(K, V)
  • Map.remove(Object, Object)
  • Map.replace(K, V, V)
  • Map.replace(K, V)
  • Map.computeIfAbsent(K, Function)
  • Map.computeIfPresent(K, BiFunction)
  • Map.compute(K, BiFunction)
  • Map.merge(K, V, BiFunction)
  • Map.getOrDefault(Object, V)
Ajouts à l'API Concurrence :
Il y a eu quelques ajouts à l'API de Concurrence, dont certains vont être brièvement discutés ici. ForkJoinPool.commonPool() est la structure qui gère toutes les opérations parallélisées sur les streams. Le pool commun est utilisé par toute ForkJoinTask qui n'est pas explicitement soumise à un pool spécifique.

ConcurrentHashMap a été complètement réécrite. Le StampedLock est
une nouvelle implémentation de lock qui peut être utilisée comme alternative à ReentrantReadWriteLock. CompletableFuture est une implémentation de l'interface Future qui fourni des méthodes pour réaliser et chaîner des tâches asynchrones.

Ajouts aux API IO/NIO :

Il y a de nouvelles méthodes d'IO/NIO, qui sont utilisées pour obtenir des java.util.stream.Stream à partir de fichiers et des input streams.
  • BufferedReader.lines()
  • Files.list(Path)
  • Files.walk(Path, int, FileVisitOption...)
  • Files.walk(Path, FileVisitOption...)
  • Files.find(Path, int, BiPredicate, FileVisitOption...)
  • Files.lines(Path, Charset)
  • DirectoryStream.stream()
Il y a aussi la nouvelle UncheckedIOException, une IOException qui étend RuntimeException. Il y a aussi CloseableStream, un flux qui peut être, et devrait être fermé.
Changements sur la Réflexion et les annotations :
Avec les annotations de type, les annotations peuvent être écrites à plus d'endroits, tels que les arguments de typage génériques comme List<@Nullable String>.
Cela améliore la détection d'erreurs par les outils d'analyse statique, ce qui renforcera et raffinera le système de type intégré à Java.

Nashorn JavaScript Engine :
Nashorn est la nouvelle implémentation légère haute performance de Javascript intégrée au JDK. Nashorn est le successeur de Rhino, qui améliore la performance et l'usage mémoire. Il supportera l'API javax.script, mais n'incluera pas le support du DOM/CSS ni d'API de plugin de navigateur.

Suivez nous sur facebook