Les nouveautés Java 7

Java 7 est la première version sous la licence GPL

Nom de code Dolphin ,  Java 7 met l’accent sur la productivité et la clareté. Nous allons voir quelques améliorations issues du projet coin de OpenJDK, mais ce n’est pas tout, d’autres fonctionnalités ont été ajoutées.

Dans cet article je vais vous décrire les nouvelles fonctionnalités que nous propose cette version, cependant la liste des fonctionnalités étant exhaustive nous traiterons uniquement la partie JPL (Java Programming Language).

Projet Coin quesaco ?

Le projet Coin a pour but de determiner quel set d’instructions sont à ajouter dans le langage Java.

Voici ce que comprend le projet Coin concernant Java 7 :

  • Strings in switch
  • Binary integral literals and underscores in numeric literals
  • Multi-catch and more precise rethrow
  • Improved type inference for generic instance creation (diamond)
  • try-with-resources statement
  • Simplified varargs method invocation

Traduction :

  • Possibilité d’effectuer un switch avec le type String.
  • Ajout d’underscore “_” dans les valeurs numériques
  • Déclaration multiple des exceptions dans un catch.
  • Simplification des génériques via l’opérateur Diamond
  • Amélioration de la gestion des ressources (system de fichier, jdbc)
  • Simplification de l’invocation contenant des paramètres varargs

Strings in switch

Désormais il est possible d’éffectuer un switch depuis le type String.

String str = "Foo";
switch (str) {
  case "Foo":
    // manage case Foo
    break;
  case "Bar":
  case "Baz":
    // manage Bar and Baz
    break;
}

Binary integral literals and underscores in numeric literals

Binary integral literals:

Cette nouveauté sera utile pour la programmation bas niveau (carte à puce, capteur, etc).
Cela permet de déclarer des littéraux entier en base 2.
Autrefois la représentation d’un type numérique ne pouvait s’écrire qu’à partir des bases 16, 10, et 8 seule celles-ci étaient autorisées.

Exemple :

// Un littéral sur 8-bit (byte).
byte aByte = (byte)0b00100001;
// un littéral sur 16-bit 'short'.
short aShort = (short)0b1010000101000101;
// Quelques littéral sur 32-bit 'int'.
int anInt1 = 0b10100001010001011010000101000101;
int anInt2 = 0b101;
int anInt3 = 0B101; // Le B peut être minuscule ou majuscule
// un littérale de 64-bit 'long'. Notez le suffix L.
long aLong = 0b1010000101000101101000010100010110100001010001011010000101000101L;

Il est donc aisé de pouvoir effectuer des masques sur ces données en base 2.

De plus cette écriture permet d’apporter de la lisibilité dans le code.

Underscores in numeric literals

Toujours dans l’esprit d’apporter de la lisibilité dans le code, il est possible d’ajouter des underscores ‘_’ dans la déclaration des types numériques.

Exemple :

//Pour écrire un millard deux cents mille
int unNombre = 1_000_200_000;
//Pour Ecrire un numéro de carte de crédit
long creditCardNumber = 1234_5678_9012_3456L;

Multi-catch and more precise rethrow

Multi-catch

Afin d’éviter d’être redondant dans le code il est possible d’effectuer plusieurs catch au sein d’un même block.

Avant :

try{
     //Instructions
}catch (IOException ex) {
     logger.log(ex);
     throw ex;
}catch (SQLException ex) {
     logger.log(ex);
     throw ex;
}

Après :

try{
     //Instructions
}catch (IOException|SQLException ex) {
    logger.log(ex);
    throw ex;
}

Cependant un inconvénient peut être noté : Lors de multiples déclarations comme ci-dessus, la variable est de type finale Il n’est donc pas possible d’accéder en écriture à cette variable pour  indiquer le message d’erreur.

Avantages : Lors de la compilation moins de bytecode sera généré.

More precise rethrow

  static class FirstException extends Exception { }
  static class SecondException extends Exception { }
  public void rethrowException(String exceptionName) throws Exception {
    try {
      if (exceptionName.equals("First")) {
        throw new FirstException();
      } else {
        throw new SecondException();
      }
    } catch (Exception e) {
      throw e;
    }
  }

Avec le code ci-dessus il n’était pas possible de renvoyer une exception de type FirstException ou SecondException car le block catch interceptait celles-ci.

Java 7 nous permet une gestion des exceptions plus fine, voici un exemple qui illustre ce qu’il est possible de faire :

  public void rethrowException(String exceptionName)
  throws FirstException, SecondException {
    try {
      if (exceptionName.equals("First")) {
        throw new FirstException();
      } else {
        throw new SecondException();
      }
    }
    catch (Exception e) {
      throw e;
    }
  }

Improved type inference for generic instance creation (diamond)

Apparues depuis la version 5, les generics permettent de définir le type d’un objet. Cependant lors de l’instantiation du constructeur il était nécessaire de spécifier à nouveau le type de l’objet.

Ce n’est plus le cas avec Java 7 :

// Avant (Java 5)
List myObjects = new ArrayList();
//depuis Java 5
List<MyObject> foo = new ArrayList<MyObject>();
// Maintenant (Java 7)
List<MyObject> foo = new ArrayList<>();

Try-with-resources statement 

Lors de l’utilisation de ressources la bonne marche à suivre est de fermer les ressources une fois que celles-ci ne sont plus utilisées. Sachez qu’avec Jave 7 il n’est plus nécessaire de  fermer ces ressources.

Chaque classe implémentant l’Interface AutoCloseable or Closeable fermera ces ressources une fois celles ci sorties du block Try.

Exemple :

//Avant (Java 6)
static String readFirstLineFromFile(String path) throws IOException {
  try (BufferedReader br = new BufferedReader(new FileReader(path))) {
    return br.readLine();
  }
}

Simplified varargs method invocation

Heap Pollution

Heap Pollution c’est quoi ?

La plupart des types paramétrés sont des types : non-reifiable types, Cela veut simplement dire que le compilateur ne peut déterminer le type de la donnée pendant la phase d’exécution.

Pourquoi ?

A la compilation le compilateur java supprime toutes les informations des types des données proposés par les génériques afin de pouvoir assurer la compatibilité lors d’utilisation d’anciennes librairies ou les génériques n’étaient pas encore d’actualité.

Un Heap Pollution apparaît lorsqu’une variable de type paramétré référence un objet qui n’est pas du type initial.

    List l = new ArrayList();
    List ls = l;       // unchecked warning
    l.add(0, new Integer(42)); // another unchecked warning
    String s = ls.get(0);      // ClassCastException is thrown

Variable Arguments Methods and Non-Reifiable Formal Parameters

Si je prends le code suivant :

  public static <T> void addToList (List<T> listArg, T... elements) {
    for (T x : elements) {
      listArg.add(x);
    }
  }

Toujours dans le même esprit le compilateur java 7 générera le warning suivant :

warning: [varargs] Possible heap pollution from parameterized vararg type T

Pourquoi ? Le  type T… elements sera transformé à la compilation par un tableau de type Object[] conséquence il y a donc la possibilité d’avoir un Heap Pollution

Suppressing Warnings from Varargs Methods with Non-Reifiable Formal Parameters

Maintenant que le compilateur nous indique les warnings il est possible de les désactiver via les annotations suivantes :

Pour une méthode statique ou une méthode qui n’est pas un constructeur.

@SafeVarargs

Seconde possibilité l’ajout de l’annotation suivante :

@SuppressWarning({“unchecked”,”varargs”})

Il est aussi possible d’ajouter l’option suivante au compilateur java

-Xlint:varargs.

About Sébastien Renno