Syntaxe et nouvelles fonctionnalités de Java 8
1. Introduction
De l'invention à la mise à niveau de la syntaxe et des fonctionnalités, Java a franchi plusieurs étapes importantes :
- Java 1.0: Commencement d'un langage de programmation.
- Java 1.1, 1.2, 1.3, 1.4 il n'y a pas beaucoup changements sur la syntaxe et les fonctionnalités.
- Java 1.5 (Ou Java 5) il y a eu de grands changements, avec l'inclusion de quelques nouveaux concepts.
- Generic
- Autoboxing/Unboxing
- fonctionnalité de mise à niveau à la boucle ("foreach").
- L'énumération est sans danger(énumérations de type-safe).
(Type-safe enumerations). - Varargs
- Importation statique (Static import)
- Metadata
- Java 6,7 il n'y a pas beaucoup de grands changements en matière de langage.
- Java 8 il y a un grand changement de langage. Avec l'inclusion de quelques nouveaux concepts et fonctionnalités :
- La méthode par défaut de l'interface (méthodes d'interface par défaut)(Default interface methods)
- L'expression Lambda (Lambda expressions)
- Méthode de références
- Annotations répétable (Repeatable annotations)
- Stream
Dans ce document, je vais vous présenter sur les fonctionnalités et la syntaxe de Java 8.
2. Méthodes par défaut pour l'interface
Java 8 vous permet d'ajouter une méthode qui n'est pas abstraite dans l'interface en utilisant le mot clé default. Cette caractéristique est également appelée Extension Methods. Voici votre premier exemple :
Formula.java
package org.o7planning.tutorial.j8.itf;
public interface Formula {
// Déclarez une méthode abstraite.
double calculate(int a);
// Déclarez une méthode qui n'est pas abstraite.
// Utilisez le mot de clé default.
// (Fonction de calcule la racine carrée d'un nombre).
default double sqrt(int a) {
return Math.sqrt(a);
}
}
Et la class FormulaImpl implémente interface Formula.
FormulaImpl.java
package org.o7planning.tutorial.j8.itf;
// Une classe implémente l'interface Formula.
public class FormulaImpl implements Formula {
// Il suffit d'implémenter les méthodes abstraites de Formula.
@Override
public double calculate(int a) {
return a * a - a;
}
}
FormulaTest.java
package org.o7planning.tutorial.j8.itf;
public class FormulaTest {
public static void main(String[] args) {
Formula formula = new FormulaImpl();
// ==> 5
double value1 = formula.sqrt(25);
System.out.println("Value1 = " + value1);
// ==> 600
double value2 = formula.calculate(25);
System.out.println("Value2 = " + value2);
}
}
3. Functional Interface
Java8 a considére que l'Interface a une seule méthode abstraite qui est Functional Interface. Vous pouvez utiliser l'annotation @FunctionalInterface pour marquer votre interface qui est Interface fonctionnelle. Elle n'est pas obligatoire. Cependant, le compilateur de Java vous avertir l'erreur si vous ajoutez accidentellement une autre méthode abstraite dans l'interface marquée par cette annotation.
Voici quelques exemples pratique avec @FunctionalInterface:
L'exemple ci-dessous est un FunctionalInterface valide, car elle n'y a qu'une seule méthode abstraite.
Foo.java
package org.o7planning.tutorial.j8.funcitf;
@FunctionalInterface
public interface Foo {
void something();
default void defaultMethod() {
System.out.println("..");
}
}
Non valide :
Valide :
Non valide :
Valide :
4. Expression Lambda
Tout d'abord, nous allons examiner la façon dont la version Java avant 8 arrange une Collection disponible.
Voyez plus :
SortBefore8Example.java
package org.o7planning.tutorial.j8.lambda;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class SortBefore8Example {
public static void main(String[] args) {
// Une liste des fruits.
List<String> fruits = Arrays.asList("Grapefruit", "Apple", "Durian", "Cherry");
// Utilisez la méthode utilitaire de Collections pour réorganiser la liste ci-dessus.
// Fournissez Comparator (Comparateur).
Collections.sort(fruits, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.compareTo(o2);
}
});
for (String fruit : fruits) {
System.out.println(fruit);
}
}
}
Les résultats d'exécution de l'exemple ci-dessus :
Apple
Cherry
Durian
Grapefruit
Java 8 comprend que les interfaces ont une méthode abstraite unique qui est Functional Interface. Par conséquent, lors de l'implémentation de l'interface, vous n'avez qu'à écrire une méthode implémente cette méthode abstraite unique. Comparator est une interface ayant une méthode abstraite unique, et c'est une Functional Interface. Vous pouvez réécrire l'exemple ci-dessus sous forme de Lambda de Java 8 :
SortJava8Example.java
package org.o7planning.tutorial.j8.lambda;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class SortJava8Example {
public static void main(String[] args) {
// Une liste des fruits.
List<String> fruits = Arrays.asList("Grapefruit", "Apple", "Durian", "Cherry");
// Utiliser la méthode utilitaire de Collections pour trier la liste ci-dessus.
// Fournir un comparateur au 2ème paramètre de la méthode.
// Le comparateur n'a qu'une seule méthode abstraite.
// ==> Peut écrire des brèves avec des expressions Lambda.
// Pas besoin d'écrire le nom de l'interface,
// Pas besoin d'écrire le nom de la méthode abstraite.
Collections.sort(fruits, (String o1, String o2) -> {
return o1.compareTo(o2);
});
for (String fruit : fruits) {
System.out.println(fruit);
}
}
}
Dans un bloc d'instruction, s'il n'y a qu'une instruction, vous pouvez effacer { }, et vous pouvez écrire cette section de code d'une manière plus concise.
Collections.sort(fruits, (String o1, String o2) -> o1.compareTo(o2) );
Compilateur de Java est même assez intelligent pour identifier le type d'éléments que vous avez besoin d'organiser, dans cet exemple, il est de type String. Ainsi, Comparator est sûrement de comparer des types de données de String. Vous pouvez l'écrire de façon plus concise.
Collections.sort(fruits, (o1, o2) -> o1.compareTo(o2));
Un autre exemple avec les expressions Lambda.
Converter.java
package org.o7planning.tutorial.j8.lambda;
@FunctionalInterface
public interface Converter<F, T> {
T convert(F from);
}
Utilisez l'interface Converter sous forme de versions Java avant la version 8 (Cela signifie ne pas utiliser Lambda).
ConverterBefore8Example.java
package org.o7planning.tutorial.j8.lambda;
public class ConverterBefore8Example {
public static void main(String[] args) {
// Initialiser l'objet Converter.
Converter<String, Integer> converter = new Converter<String, Integer>() {
@Override
public Integer convert(String from) {
return Integer.parseInt(from);
}
};
// ==> 100
Integer value = converter.convert("0100");
System.out.println("Value = " + value);
}
}
Utilisez les expressions Lambda de Java 8 :
ConveterJava8Example.java
package org.o7planning.tutorial.j8.lambda;
public class ConveterJava8Example {
public static void main(String[] args) {
// Converter est un FunctionalInterface
// Utilisez la syntaxe de Java 8 (Lambda)
// Dans le cas : Créer l'objet directement à partir de FunctionalInterface.
Converter<String, Integer> converter1 = (String from) -> {
return Integer.parseInt(from);
};
// ==> 100
Integer value1 = converter1.convert("0100");
System.out.println("Value1 = " + value1);
// Ou plus simple :
Converter<String, Integer> converter2 = (from) -> Integer
.parseInt(from);
// ==> 200
Integer value2 = converter2.convert("00200");
System.out.println("Value2 = " + value2);
// Si la méthode n'a qu'un seul paramètre, peut ignorer ().
Converter<String, Integer> converter3 = from -> Integer
.parseInt(from);
// ==> 300
Integer value3 = converter3.convert("00300");
System.out.println("Value3 = " + value3);
}
}
5. Functional Interface API
Java 8 dispose d'un grand nombre des Functional Interface disponibles dans le package java.util.function. Ici, je vais vous donner des instructions d'utilisation certaines de ces interfaces afin que vous puissiez comprendre plus facilement l'expression Lambda et leur commodité.
java.util.function.Consumer
Consumer est une Functional interface disponible de Java 8, elle a une seule méthode abstraite qui accepte un paramètre d'entrée et cette méthode ne renvoie rien.
Consumer.java
package java.util.function;
import java.util.Objects;
@FunctionalInterface
public interface Consumer<T> {
// Méthode pour accepter un paramètre d'entrée
// Et ne renvoie rien.
void accept(T t);
}
Utilisez la methode List.forEach(Consumer) :
// java.util.List extends java.util.Collection (extends Iterable)
// Interface java.util.Iterable:
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
ConsumerExample.java
package org.o7planning.tutorial.j8.api;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
public class ConsumerExample {
// Utiliser la méthode List.forEach (Consumer) avec la syntaxe de Java <8.
// Imprimer la liste des éléments de List.
public static void beforeJ8() {
List<String> list = Arrays.asList("a", "b", "c", "a1", "a2");
list.forEach(new Consumer<String>() {
@Override
public void accept(String t) {
System.out.println(t);
}
});
}
// Utiliser la méthode List.forEach(Consumer) avec la syntaxe de Java 8.
// Utiliser expression Lambda.
public static void java8Consumer() {
List<String> list = Arrays.asList("a", "b", "c", "a1", "a2");
list.forEach((String t) -> {
System.out.println(t);
});
}
// Utiliser la méthode List.forEach(Consumer) avec la syntaxe de Java 8.
// Utiliser expressions Lambda.
// (Plus simple)
public static void java8ConsumerMoreSimple() {
List<String> list = Arrays.asList("a", "b", "c", "a1", "a2");
list.forEach((String t) -> System.out.println(t));
}
}
java.util.function.Predicate
Predicate est une Functional interfacedisponible de Java8, elle a une méthode abstraite qui accepte un paramètre d'entrée unique et la méthode renvoie une valeur boolean (true/false). Cette méthode est d'évaluer si le paramètre d'entrée convient à quelque chose de logique ou non.
Predicate.java
package java.util.function;
import java.util.Objects;
@FunctionalInterface
public interface Predicate<T> {
// Évalue un paramètre d'entrée et renvoie true ou false.
boolean test(T t);
}
Dans l'exemple suivant, nous allons filtrer une liste d'entiers et imprimer une liste de nombres impairs en utilisant Predicate sous la forme de Java8 et des versions précédentes.
PredicateExample.java
package org.o7planning.tutorial.j8.api;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Stream;
public class PredicateExample {
// Utiliser la méthode Stream.filter(Predicate<T>) avec la syntaxe de Java < 8.
// Filtrer une liste d'entiers et imprime les impaires.
public static void beforeJ8() {
List<Integer> list = Arrays.asList(1, 4, 5, 1, 7, 8);
// Stream contient les éléments de la liste au-dessus
Stream<Integer> stream = list.stream();
// Un nouveau Stream contient des impairs.
Stream<Integer> stream2 = stream.filter(new Predicate<Integer>() {
@Override
public boolean test(Integer t) {
return t % 2 == 1;
}
});
}
// Utiliser la méthode Stream.filter(Predicate<T>) avec la syntaxe de Java >= 8.
// Filtrer une liste d'entiers et imprime les impaires.
// Avec l'utilisation d'expressions Lambda.
public static void java8Predicate() {
List<Integer> list = Arrays.asList(1, 4, 5, 1, 7, 8);
// Un Stream contient les éléments de la liste au-dessus
Stream<Integer> stream = list.stream();
// Un nouveau Stream contient des impairs.
Stream<Integer> stream2 = stream.filter(t -> {
return t % 2 == 1;
});
// Stream.forEach(Consumer<T>)
stream2.forEach(t -> System.out.println(t));
}
// Simple et plus concis.
public static void java8ConsumerMoreSimple() {
List<Integer> list = Arrays.asList(1, 4, 5, 1, 7, 8);
// Un Stream contient les éléments de la liste au-dessus
Stream<Integer> stream = list.stream();
stream.filter(t -> t % 2 == 1).forEach(t -> System.out.println(t));
}
}
java.util.function.Function
Function est un Functional interface disponibe de Java 8, elle a une méthode abstraite qui accepte un paramètre d'entrée et la méthode renvoie un objet différent.
Function.java
package java.util.function;
import java.util.Objects;
@FunctionalInterface
public interface Function<T, R> {
// Cette méthode accepte un paramètre.
// Et renvoie le résultat.
R apply(T t);
}
Exemple :Donner une liste de String, imprimer les éléments de la liste en majuscules.
FunctionExample.java
package org.o7planning.tutorial.j8.api;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Stream;
public class FunctionExample {
// Utiliser la méthode Stream.map(Function) avec la syntaxe de Java < 8.
// Imprimer la liste des éléments de List.
public static void beforeJ8() {
List<String> list = Arrays.asList("a", "c", "B", "e", "g");
// Stream contient les éléments de la liste.
Stream<String> stream = list.stream();
// Stream.map(Function):
// <R> Stream<R> map(Function<? super T, ? extends R> mapper);
// Renvoie un nouveau Stream, avec les éléments ont été modifiés.
Stream<String> streamUpper = stream.map(new Function<String, String>() {
@Override
public String apply(String t) {
return t == null ? null : t.toUpperCase();
}
});
streamUpper.forEach(t -> System.out.println(t));
}
public static void java8Function() {
List<String> list = Arrays.asList("a", "c", "B", "e", "g");
// Un Stream contient les éléments de la liste.
Stream<String> stream = list.stream();
stream.map(t -> t == null ? null : t.toUpperCase()).forEach(t -> System.out.println(t));
}
public static void main(String[] args) {
beforeJ8();
java8Function();
}
}
Certains Functional interface similaires:
- java.util.function.IntFunction<R>
- java.util.function.DoubleFunction<R>
- java.util.function.LongFunction<R>
@FunctionalInterface
public interface IntFunction<R> {
R apply(int value);
}
@FunctionalInterface
public interface LongFunction<R> {
R apply(long value);
}
@FunctionalInterface
public interface DoubleFunction<R> {
R apply(double value);
}
java.util.function.Supplier
Supplier est un Functional interface disponibe de Java 8, elle a une seule méthode abstraite qui n'a pas paramètre et renvoie un objet.
Supplier.java
package java.util.function;
@FunctionalInterface
public interface Supplier<T> {
// Cette méthode n'a pas de paramètre.
// Mais renvoie un résultat.
T get();
}
SupplierExample.java
package org.o7planning.tutorial.j8.api;
import java.util.function.Supplier;
public class SupplierExample {
// Une méthode dont le paramètre est Supplier<String>.
public static void display(Supplier<String> supp) {
System.out.println(supp.get());
}
// N'utilisez pas d'expressions Lambda.
public static void beforeJ8() {
display(new Supplier<String>() {
@Override
public String get() {
return "Hello";
}
});
display(new Supplier<String>() {
@Override
public String get() {
return "World";
}
});
}
// Utilisez l'expression Lambda.
public static void java8Supplier() {
display(() -> {
return "Hello";
});
display(() -> {
return "World";
});
}
// Utilisez l'expression Lambda.
// (plus concis).
public static void java8SupplierShortest() {
display(() -> "Hello");
display(() -> "World");
}
public static void main(String[] args) {
beforeJ8();
System.out.println("-----------");
java8SupplierShortest();
}
}
Certaines s Functional Interface similaires :
- java.util.function.BooleanSupplier
- java.util.function.IntSupplier
- java.util.function.DoubleSupplier
- java.util.function.LongSupplier
6. Method reference
C'est une caractéristique qui est liée à l'expression Lambda. Il nous permet de référencer des constructeurs ou des méthodes sans les exécuter. Les références de méthode et Lambda sont similaires en ce sens qu'elles exigent toutes deux un type d'objectif constitué d'une Functional Interface compatible.
Java 8 vous permet de passer des références de méthodes ou de constructeurs via le : : mot-clé
Before looking at details, let's see a simple example.
MyFunction est un Functional Interface. Elle définit une méthode qui prend deux paramètres, int a et b, et renvoie la valeur de int.
MyFunction.java
package org.o7planning.tutorial.j8.mref;
@FunctionalInterface
public interface MyFunction {
// Cette méthode a deux paramètres, a et b, et renvoie un int.
public int doSomething(int a, int b);
}
MyMathUtils est une classe avec deux méthodes statiques utilisées pour calculer la somme et la soustraction de deux nombres entiers.
MyMathUtils.java
package org.o7planning.tutorial.j8.mref;
public class MyMathUtils {
// Cette méthode a deux paramètres, a et b, et renvoie un int.
// Cette méthode est différente du nom,
// mais la structure similaire à MyFunction.doSomething(int,int).
public static int sum(int a, int b) {
return a + b;
}
public static int minus(int a, int b) {
return a - b;
}
}
MethodReferenceExample.java
package org.o7planning.tutorial.j8.mref;
public class MethodReferenceExample {
// Le troisième paramètre de cette méthode est MyFunction (Functional Interface).
// Lorsque vous utilisez cette méthode:
// Vous pouvez passer la référence d'une méthode au 3ème paramètre.
// (Les méthodes doivent être du même type que MyFunction)
public static int action(int a, int b, MyFunction func) {
return func.doSomething(a, b);
}
public static void main(String[] args) {
int a = 100;
int b = 30;
// Passer la référence de la méthode MyMathUtils.sum.
int c = action(a, b, MyMathUtils::sum);// ==> 130.
System.out.println("c = " + c);
// Passer la référence de la méthode MyMathUtils.minus.
int d = action(a, b, MyMathUtils::minus);// ==> 70
System.out.println("d = " + d);
// Passer la référence de la méthode Math.subtractExact.
int e = action(a, b, Math::subtractExact);// ==> 70
System.out.println("e = " + e);
// Passer la référence de la méthode Math.min.
int f = action(a, b, Math::min);// ==> 30
System.out.println("f = " + f);
}
}
A travers l'exemple ci-dessus, vous pouvez voir comment utiliser le mot clé : : pour passer la référence d'une méthode. Si vous appelez une méthode et qu'il existe un argument appelé Functional Interface dans cette méthode, vous pouvez transmettre une référence de méthode dont la structure est similaire à celle définie dans Functional Interface.
Java Basic
- Personnaliser le compilateur Java pour traiter votre annotation (Annotation Processing Tool)
- Programmation Java pour l'équipe utilisant Eclipse et SVN
- Le Tutoriel de Java WeakReference
- Le Tutoriel de Java PhantomReference
- Tutoriel sur la compression et la décompression Java
- Configuration d'Eclipse pour utiliser le JDK au lieu de JRE
- Méthodes Java String.format() et printf()
- Syntaxe et nouvelles fonctionnalités de Java 8
- Expression régulière en Java
- Tutoriel de programmation Java multithreading
- Bibliothèques de pilotes JDBC pour différents types de bases de données en Java
- Tutoriel Java JDBC
- Obtenir des valeurs de colonne automatiquement incrémentées lors de l'insertion d'un enregistrement à l'aide de JDBC
- Le Tutoriel de Java Stream
- Le Tutoriel de Java Functional Interface
- Introduction à Raspberry Pi
- Le Tutoriel de Java Predicate
- Classe abstraite et interface en Java
- Modificateurs d'accès en Java
- Le Tutoriel de Java Enum
- Le Tutoriel de Java Annotation
- Comparer et trier en Java
- Le Tutoriel de Java String, StringBuffer et StringBuilder
- Tutoriel de gestion des exceptions Java
- Le Tutoriel de Java Generics
- Manipulation de fichiers et de répertoires en Java
- Le Tutoriel de Java BiPredicate
- Le Tutoriel de Java Consumer
- Le Tutoriel de Java BiConsumer
- Qu'est-ce qui est nécessaire pour commencer avec Java?
- L'histoire de Java et la différence entre Oracle JDK et OpenJDK
- Installer Java sur Windows
- Installer Java sur Ubuntu
- Installer OpenJDK sur Ubuntu
- Installer Eclipse
- Installer Eclipse sur Ubuntu
- Le Tutoriel Java pour débutant
- Histoire des bits et des bytes en informatique
- Types de données dans Java
- Opérations sur les bits
- Le Tutoriel de instruction Java If else
- Le Tutoriel de instruction Java Switch
- Les Boucles en Java
- Les Tableaux (Array) en Java
- JDK Javadoc au format CHM
- Héritage et polymorphisme en Java
- Le Tutoriel de Java Function
- Le Tutoriel de Java BiFunction
- Exemple de Java encoding et decoding utilisant Apache Base64
- Le Tutoriel de Java Reflection
- Invocation de méthode à distance en Java
- Le Tutoriel de Java Socket
- Quelle plate-forme devez-vous choisir pour développer des applications de bureau Java?
- Le Tutoriel de Java Commons IO
- Le Tutoriel de Java Commons Email
- Le Tutoriel de Java Commons Logging
- Comprendre Java System.identityHashCode, Object.hashCode et Object.equals
- Le Tutoriel de Java SoftReference
- Le Tutoriel de Java Supplier
- Programmation orientée aspect Java avec AspectJ (AOP)
Show More
- Tutoriels de programmation Java Servlet/JSP
- Tutoriels de Java Collections Framework
- Tutoriels Java API pour HTML & XML
- Tutoriels Java IO
- Tutoriels Java Date Time
- Tutoriels Spring Boot
- Tutoriels Maven
- Tutoriels Gradle
- Tutoriels Java Web Service
- Tutoriels de programmation Java SWT
- Tutoriels de JavaFX
- Tutoriels Java Oracle ADF
- Tutoriels Struts2
- Tutoriels Spring Cloud