NetBeans 6.5 est parmis nous

La version 6.5 de l'IDE NetBeans viens de sortir, en version finale.

Après téléchargement et installation, la première impression est assez marquante. Le lancement est encore plus rapide, et l'interface encore plus fluide (comparé à la version 6.1).

Au niveau des nouvelles fonctionnalités, quelques nouveautés assez importantes :
  • Environnement de développement PHP (et une distribution de NetBeans spécialisée)
  • Amélioration du support Java EE (notamment JSF et JPA)
  • Éditeur Java FX
  • Support de GlassFish v3 prelude, uniquement pour de développement Web
  • Amélioration de l'éditeur Java
  • Nouvelles fonctionnalités dans l'IDE de base
    • Compile on save / Deploy on save
    • Modification des préférences d'indentation par projet
    • Barre de recherche rapide
La liste complète est disponible ici.

Parmis ces fonctionnalités, certaines me plaisent déjà, dont :
  • Le "compile/deploy on save" qui recompile et/ou redéploie un projet dès qu'un changement est fait dans un fichier
  • Le support de GlassFish v3 prelude (que j'aime déjà, pour sa rapidité, et ses derniers frameworks [EJB 3.1, JSF 2.0])
  • Les préférences d'indentation spécifique à chaque projet. Finies les guerres d'indentation sur les dépots !

Il y a aussi quelques fonctionnalités qui restent à tester et qui semblent intéressantes, comme le support amélioré de JSF et de JPA.

Pour les téléchargements, c'est directement ici.

Permalink  |  Commentaires (2)

Java 7 : Meilleure gestion des exceptions

Une nouvelle proposition pour Java 7 est à l'ordre du jour : l'amélioration de la gestion des exceptions.

Cette amélioration consisterait en deux parties :
  • Une amélioration pour relever les exception attrapées.
  • La possibilité d'attraper plusieurs types d'exceptions dans un seul bloc catch

Relever une exception déjà attrapée

Lors de la rédaction de libraires en Java, il arrive couramment d'avoir à attraper une exception, d'effectuer certains traitements, certains enregistrements dans des fichiers de log, puis de vouloir la relancer derrière. Un petit exemple (inspiré de la proposition originale) :
try {
    throw new MyException();
} catch (Throwable t) {
    // Log the exception
    throw t;
}

Un tel code est entièrement valide, mais contraignant. En effet, essayons de l'encapsuler dans une méthode :
public void doSomeStuff() throws Throwable {
    try {
        throw new MyException();
    } catch (Throwable t) {
        // Log the exception
        throw t;
    }
}

J'ai été obligé de rajouter un magnifique throws Throwable. Pourquoi ? Tout simplement parce que la ligne throw t; lève une exception, de type Throwable. Le compilateur impose donc de déclarer Throwable dans le prototype de la méthode. Et ce, même si le bloc try ne lève que des exceptions de type MyException, dans notre exemple.

Des techniques pour palier à ce problème sont assez répandues, comme par exemple l'encapsulation de l'exception levée dans une RuntimeException. Mais on perd tout le bénéfice des exceptions vérifiées.

L'amélioration dans ce cas là consisterais à pouvoir attraper les exceptions en les marquant final. L'exception marquée final ne pouvant changer, le compilateur est certain que la ligne throw t; ne lèvera qu'une exception levée dans le bloc try. Dans notre cas, une exception de type MyException. L'exception MyException serait donc la seule à déclarer. Et ce code deviendrait complètement valide :
public void doSomeStuff() throws MyException {
    try {
        throw new MyException();
    } catch (final Throwable t) {
        // Log the exception
        throw t;
    }
}

Attraper plusieurs types d'exceptions dans un bloc catch

Un simple petit exemple devrait clarifier la situation sur cette nouvelle fonctionnalité :
try {
    klass.newInstance();
} catch (InstantiationException ex) {
    ex.printStackTrace(System.err);
} catch (IllegalAccessException ex) {
    ex.printStackTrace(System.err);
}

Pour récupérer deux exceptions (InstantiationException et IllegalAccessException), deux blocs catch sont obligatoires. Même si le même traitement est effectué à l'intérieur. Dans notre cas, l'amélioration consisterais à permettre au développeur d'attraper deux types d'exceptions dans un seul bloc catch (inspiré de la proposition originale) :
try {
    klass.newInstance();
} catch (InstantiationException | IllegalAccessException ex) {
    ex.printStackTrace(System.err);
}

Dans cet exemple, le bloc catch est capable d'attraper les exception de type InstantiationException et celles de type IllegalAccessException.

Une autre syntaxe a été proposée, cette fois-ci basée sur les generics :
try {
    // Some code...
} <T extends MyException> catch (T t) {
    // Catch here...
}

Une évolution plus radicale

Une autre évolution concernant les exceptions est débattue par les utilisateurs de Java ici et .

Le débat tourne autour de la justification des exceptions vérifiées en Java. Est-ce que les exceptions vérifiées sont utiles, où alors devraient elles être toutes remplacées par des exceptions non vérifiées ?

Pour rappel, une exception vérifiée est une exception qui doit obligatoirement être soit déclarée (via throws), soit être attrapée (via catch).

Je dois avouer que je suis plutôt du coté des "défenseurs" des exceptions vérifiées, même si elles sont assez contraignantes à mettre en place dans certaines situation, notamment pour l'introduction des closures.

Permalink  |  Commentaires (0)

Astuce Java #2 : abstract et final vs interface et enum

Nouvelle question existentielle (je commence à croire que les questions nous viennent au rythme de une par jour en ce moment...).

Ce fois ci : Quelles sont les combinaisons possible en mélangeant les mots clés abstract et final avec les mots clés interface et enum ?

On pourrait résumer l'intégralité de cette question de cette manière :
Lesquelles de ces différentes combinaisons de mots clés sont autorisées pour déclarer un type ?
abstract final
interface ? ?
enum ? ?

Voici ce à quoi on aurait pu s'attendre :
abstract final
interface Illégal Légal
enum Légal Illégal

Je m'explique :
  • Une interface est par définition abstraite, abstract serait donc bien absurde dans ce cas.
  • Une interface pourrait être finale comme les classes le sont pour interdire l'héritage. On pourrait donc continuer à implémenter une interface, mais on ne pourrait pas en hériter (pour rappel, une interface hérite d'une autre).
  • Une énumération peut contenir des méthodes. Donc pourquoi pas des méthodes abstraites ?
  • Les types "enum" se sont pas extensibles (on ne peut pas les hériter), donc un final ici serait absurde une fois de plus.

Et bien voilà, après tests, ce que l'on obtient :
abstract final
interface Légal Illégal
enum Illégal Illégal

Trois surprises :
  • Il est possible de rendre une interface abstraite. Le comportement de l'interface n'est en rien modifié. D'après la Java Language Specification (Third edition), § 9.1.1.1 :
    Every interface is implicitly abstract. This modifier is obsolete and should not be used in new programs.
    The Java Language Specification, Third Edition, § 9.1.1.1
  • Il n'est pas possible de rendre une interface finale.
  • Il n'est pas possible de mettre des méthodes abstraites dans une énumération.

Je m'attendais pas vraiment à ces résultats, je vais retourner traîner à la recherche d'une explication sur ces points (car explication il doit y avoir).

Permalink  |  Commentaires (1)