Nouvelles fonctionnalités de Java 8

Nouvelles fonctionnalités de Java 8

1. Vue d'ensemble

Dans cet article, nous examinerons rapidement certaines des nouvelles fonctionnalités les plus intéressantes de Java 8.

Nous parlerons de: méthodes par défaut et statiques de l'interface, référence de méthode et facultatif.

Nous avons déjà couvert certaines des fonctionnalités de la version de Java 8 -stream API,lambda expressions and functional interfaces - car ce sont des sujets complets qui méritent un examen séparé.

2. Interface par défaut et méthodes statiques

Avant Java 8, les interfaces ne pouvaient avoir que des méthodes abstraites publiques. Il n'a pas été possible d'ajouter de nouvelles fonctionnalités à l'interface existante sans obliger toutes les classes d'implémentation à créer une implémentation des nouvelles méthodes, pas plus que de créer des méthodes d'interface avec une implémentation.

À partir de Java 8, les interfaces peuvent avoir des méthodesstatic etdefault qui, bien qu'elles soient déclarées dans une interface, ont un comportement défini.

2.1. Méthode statique

Considérez la méthode suivante de l'interface (appelons cette interfaceVehicle):

static String producer() {
    return "N&F Vehicles";
}

La méthode statiqueproducer() est disponible uniquement via et à l'intérieur d'une interface. Il ne peut pas être remplacé par une classe d'implémentation.

Pour l'appeler en dehors de l'interface, l'approche standard pour l'appel de méthode statique doit être utilisée:

String producer = Vehicle.producer();

2.2. Méthode par défaut

Les méthodes par défaut sont déclarées en utilisant les nouveauxdefault keyword. Celles-ci sont accessibles via l'instance de la classe d'implémentation et peuvent être remplacées.

Ajoutons une méthodedefault à notre interfaceVehicle, qui fera également un appel à la méthodestatic de cette interface:

default String getOverview() {
    return "ATV made by " + producer();
}

Supposons que cette interface est implémentée par la classeVehicleImpl. Pour exécuter la méthodedefault, une instance de cette classe doit être créée:

Vehicle vehicle = new VehicleImpl();
String overview = vehicle.getOverview();

3. Références de méthode

La référence à la méthode peut être utilisée comme alternative plus courte et plus lisible pour une expression lambda qui appelle uniquement une méthode existante. Il existe quatre variantes de références de méthodes.

3.1. Référence à une méthode statique

La référence à une méthode statique contient la syntaxe suivante:ContainingClass::methodName.

Essayons de compter toutes les chaînes vides dans lesList<String> à l'aide de l'API Stream.

boolean isReal = list.stream().anyMatch(u -> User.isRealUser(u));

Examinez de plus près l'expression lambda dans la méthodeanyMatch(), elle fait simplement un appel à une méthode statiqueisRealUser(User user) de la classeUser. Donc, il peut être remplacé par une référence à une méthode statique:

boolean isReal = list.stream().anyMatch(User::isRealUser);

Ce type de code semble beaucoup plus informatif.

3.2. Référence à une méthode d'instance

La référence à une méthode d'instance contient la syntaxe suivante:containingInstance::methodName. Le code suivant appelle la méthodeisLegalName(String string) de typeUser qui valide un paramètre d'entrée:

User user = new User();
boolean isLegalName = list.stream().anyMatch(user::isLegalName);

3.3. Référence à une méthode d'instance d'un objet d'un type particulier

Cette méthode de référence utilise la syntaxe suivante:ContainingType::methodName. Un exemple
long count = list.stream().filter(String::isEmpty).count();

3.4. Référence à un constructeur

Une référence à un constructeur prend la syntaxe suivante:ClassName::new. Comme le constructeur en Java est une méthode spéciale, la référence de méthode peut également lui être appliquée à l'aide denew comme nom de méthode.

Stream stream = list.stream().map(User::new);

4. Facultatif

Avant Java 8, les développeurs devaient valider soigneusement les valeurs auxquelles ils se référaient, en raison de la possibilité de lancer lesNullPointerException (NPE). Toutes ces vérifications demandaient un code passe-partout assez ennuyeux et sujet aux erreurs.

La classe Java 8Optional<T> peut aider à gérer les situations où il y a une possibilité d'obtenir leNPE. Elle fonctionne comme un conteneur pour l'objet de typeT. Elle peut renvoyer une valeur de cet objet si cette valeur n'est pas unnull. Lorsque la valeur à l'intérieur de ce conteneur estnull, cela permet d'effectuer des actions prédéfinies au lieu de lancerNPE.

4.1. Création desOptional<T>

Une instance de la classeOptional peut être créée à l'aide de ses méthodes statiques:

Optional optional = Optional.empty();

Renvoie unOptional. vide

String str = "value";
Optional optional = Optional.of(str);

Renvoie unOptional qui contient une valeur non nulle.

Optional optional = Optional.ofNullable(getString());

Renvoie unOptional avec une valeur spécifique ou unOptional vide si le paramètre estnull.

4.2. Optional<T> usage

Par exemple, vous vous attendez à obtenir unList<String> et dans le cas denull, vous voulez le remplacer par une nouvelle instance d'unArrayList<String>.W avec le code pré-Java 8 vous besoin de faire quelque chose comme ça:

List list = getList();
List listOpt = list != null ? list : new ArrayList<>();

Avec Java 8, la même fonctionnalité peut être obtenue avec un code beaucoup plus court:

List listOpt = getList().orElseGet(() -> new ArrayList<>());

Il y a encore plus de code standard lorsque vous devez atteindre le champ d'un objet à l'ancienne. Supposons que vous ayez un objet de typeUser qui a un champ de typeAddress avec un champ street de typeString. Et pour une raison quelconque, vous devez renvoyer une valeur de le champstreet s'il en existe ou une valeur par défaut sistreet estnull:

User user = getUser();
if (user != null) {
    Address address = user.getAddress();
    if (address != null) {
        String street = address.getStreet();
        if (street != null) {
            return street;
        }
    }
}
return "not specified";

Cela peut être simplifié avecOptional:

Optional user = Optional.ofNullable(getUser());
String result = user
  .map(User::getAddress)
  .map(Address::getStreet)
  .orElse("not specified");

Dans cet exemple, nous avons utilisé la méthodemap() pour convertir les résultats de l'appel desgetAdress() enOptional<Address> etgetStreet() enOptional<String>. Si l'une de ces méthodes renvoyaitnull la méthodemap() renverrait unOptional. vide

Imaginez que nos getters renvoientOptional<T>. Donc, nous devrions utiliser la méthodeflatMap() au lieu desmap():

Optional optionalUser = Optional.ofNullable(getOptionalUser());
String result = optionalUser
  .flatMap(OptionalUser::getAddress)
  .flatMap(OptionalAddress::getStreet)
  .orElse("not specified");

Un autre cas d'utilisation deOptional est la modification deNPE avec une autre exception. Donc, comme nous l'avons fait précédemment, essayons de faire ceci dans le style pré-Java 8:

String value = null;
String result = "";
try {
    result = value.toUpperCase();
} catch (NullPointerException exception) {
    throw new CustomException();
}

Et si nous utilisonsOptional<String>? La réponse est plus lisible et plus simple:

String value = null;
Optional valueOpt = Optional.ofNullable(value);
String result = valueOpt.orElseThrow(CustomException::new).toUpperCase();

Notez que comment et dans quel but utiliserOptional dans votre application est une décision de conception sérieuse et controversée, et l'explication de tous ses avantages et inconvénients est hors de la portée de cet article. Si vous êtes intéressé, vous pouvez aller plus loin, il existe de nombreux articles intéressants sur Internet consacrés à ce problème. This one etthis another one pourraient être très utiles.

5. Conclusion

Dans cet article, nous discutons brièvement de certaines nouvelles fonctionnalités intéressantes de Java 8.

Il existe bien sûr de nombreux autres ajouts et améliorations qui sont répartis sur de nombreux packages et classes Java 8 JDK.

Cependant, les informations illustrées dans cet article constituent un bon point de départ pour explorer et apprendre certaines de ces nouvelles fonctionnalités.

Enfin, tout le code source de l'article est disponibleover on GitHub.