Questions d’entretien d’embauche Java 8 (Réponses)

Questions d'entretien d'embauche Java 8 (+ réponses)

1. introduction

Dans cet article, nous allons explorer certaines des questions liées à JDK8 qui pourraient apparaître lors d'une interview.

Java 8 est une version de plate-forme contenant de nouvelles fonctionnalités linguistiques et de nouvelles classes de bibliothèques. La plupart de ces nouvelles fonctionnalités visent à obtenir un code plus propre et plus compact, et certaines ajoutent de nouvelles fonctionnalités qui n’ont jamais été prises en charge en Java.

Lectures complémentaires:

Questions d'entretiens chez Memory Management in Java (+ Réponses)

Un ensemble de questions d’entrevue populaires liées à la gestion de la mémoire et bien sûr de réponses.

Read more

Questions d'entretiens chez Java Collections

Un ensemble de questions pratiques sur les entretiens avec Java relatives aux collections

Read more

2. Connaissances générales Java 8

Q1. Quelles nouvelles fonctionnalités ont été ajoutées à Java 8?

Java 8 est livré avec plusieurs nouvelles fonctionnalités, mais les plus importantes sont les suivantes:

  • Lambda Expressions - une nouvelle fonctionnalité de langage permettant de traiter les actions comme des objets

  • Method References - permet de définir les expressions Lambda en faisant référence aux méthodes directement à l'aide de leurs noms

  • Optional - classe d'enveloppe spéciale utilisée pour exprimer le caractère facultatif

  • Functional Interface - une interface avec au maximum une méthode abstraite, l'implémentation peut être fournie à l'aide d'une expression Lambda

  • Default methods - nous donne la possibilité d'ajouter des implémentations complètes dans les interfaces en plus des méthodes abstraites

  • Nashorn, JavaScript Engine - moteur basé sur Java pour exécuter et évaluer du code JavaScript

  • Stream API - une classe d'itérateur spéciale qui permet de traiter des collections d'objets de manière fonctionnelle

  • Date API - une API de date améliorée et immuable inspirée de JodaTime

Parallèlement à ces nouvelles fonctionnalités, de nombreuses améliorations sont apportées au niveau du compilateur et de la JVM.

3. Références de méthode

Q1. Qu'est-ce qu'une référence de méthode?

Une référence de méthode est une construction Java 8 qui peut être utilisée pour référencer une méthode sans l'invoquer. Il est utilisé pour traiter les méthodes comme des expressions Lambda. Ils ne fonctionnent que comme sucre syntaxique pour réduire la verbosité de certains lambdas. De cette façon, le code suivant:

(o) -> o.toString();

peut devenir:

Object::toString();

Une référence de méthode peut être identifiée par un double deux-points séparant un nom de classe ou d'objet et le nom de la méthode. Il comporte différentes variantes telles que la référence du constructeur:

String::new;

Référence de méthode statique:

String::valueOf;

Référence de la méthode d'instance liée:

str::toString;

Référence de la méthode d'instance non liée:

String::toString;

Vous pouvez lire une description détaillée des références de méthode avec des exemples complets en suivantthis link etthis one.

Q2. Quelle est la signification de String :: Valueof Expression?

Il s'agit d'une référence de méthode statique à la méthodevalueOf de la classeString.

4. Optionnel

Q1. Qu'est-ce queOptional? Comment peut-il être utilisé?

Optional est une nouvelle classe dans Java 8 qui encapsule une valeur facultative, c'est-à-dire une valeur qui est ou non. C'est un wrapper autour d'un objet, et vous pouvez le considérer comme un conteneur de zéro ou d'un élément.

Optional a une valeur spécialeOptional.empty() au lieu denull encapsulé. Ainsi, il peut être utilisé à la place d'une valeur nullable pour se débarrasser deNullPointerException dans de nombreux cas.

Vous pouvez lire un article dédié surOptionalhere.

L'objectif principal deOptional, tel que conçu par ses créateurs, était d'être un type de retour de méthodes qui renvoyaient auparavantnull. De telles méthodes vous obligeraient à écrire du code passe-partout pour vérifier la valeur de retour et pourraient parfois oublier de faire une vérification défensive. Dans Java 8, un type de retourOptional vous oblige explicitement à gérer différemment les valeurs encapsulées nulles ou non nulles.

Par exemple, la méthodeStream.min() calcule la valeur minimale dans un flux de valeurs. Mais que se passe-t-il si le flux est vide? Si ce n'était pas pourOptional, la méthode renverraitnull ou lèverait une exception.

Mais il renvoie une valeurOptional qui peut êtreOptional.empty() (le deuxième cas). Cela nous permet de gérer facilement un tel cas:

int min1 = Arrays.stream(new int[]{1, 2, 3, 4, 5})
  .min()
  .orElse(0);
assertEquals(1, min1);

int min2 = Arrays.stream(new int[]{})
  .min()
  .orElse(0);
assertEquals(0, min2);

Il convient de noter queOptional n’est pas une classe à usage général commeOption dans Scala. Il n'est pas recommandé de l'utiliser comme valeur de champ dans les classes d'entité, ce qui est clairement indiqué par le fait qu'il n'implémente pas l'interfaceSerializable.

5. Interfaces fonctionnelles

Q1. Décrivez certaines des interfaces fonctionnelles de la bibliothèque standard.

Il existe de nombreuses interfaces fonctionnelles dans le packagejava.util.function, les plus courantes incluent, mais sans s'y limiter:

  • Function - il prend un argument et renvoie un résultat

  • Consumer - il prend un argument et ne renvoie aucun résultat (représente un effet secondaire)

  • Supplier - il ne prend pas d'argument et renvoie un résultat

  • Predicate - il prend un argument et renvoie un booléen

  • BiFunction - il prend deux arguments et renvoie un résultat

  • BinaryOperator - il est similaire à unBiFunction, prenant deux arguments et renvoyant un résultat. Les deux arguments et le résultat sont tous du même type

  • UnaryOperator - il est similaire à unFunction, prenant un seul argument et renvoyant un résultat du même type

Pour en savoir plus sur les interfaces fonctionnelles, consultez l'article“Functional Interfaces in Java 8”.

Q2. Qu'est-ce qu'une interface fonctionnelle? Quelles sont les règles de définition d'une interface fonctionnelle?

Une interface fonctionnelle est une interface avec ni plus, ni moins mais une seule méthode abstraite (les méthodesdefault ne comptent pas).

Lorsqu'une instance d'une telle interface est requise, une expression Lambda peut être utilisée à la place. Plus formellement, lesFunctional interfaces fournissent des types de cible pour les expressions lambda et les références de méthode.

Les arguments et le type de retour de cette expression correspondent directement à ceux de la méthode abstraite unique.

Par exemple, l'interfaceRunnable est une interface fonctionnelle, donc au lieu de:

Thread thread = new Thread(new Runnable() {
    public void run() {
        System.out.println("Hello World!");
    }
});

vous pouvez simplement faire:

Thread thread = new Thread(() -> System.out.println("Hello World!"));

Les interfaces fonctionnelles sont généralement annotées avec l'annotation@FunctionalInterface - qui est informative et n'affecte pas la sémantique.

6. Méthode par défaut

Q1. Qu'est-ce qu'une méthode par défaut et quand l'utilisons-nous?

Une méthode par défaut est une méthode avec une implémentation - qui peut être trouvée dans une interface.

Nous pouvons utiliser une méthode par défaut pour ajouter une nouvelle fonctionnalité à une interface tout en conservant une compatibilité ascendante avec les classes qui implémentent déjà l'interface:

public interface Vehicle {
    public void move();
    default void hoot() {
        System.out.println("peep!");
    }
}

Habituellement, quand une nouvelle méthode abstraite est ajoutée à une interface, toutes les classes implémentées sont interrompues jusqu'à ce qu'elles implémentent la nouvelle méthode abstraite. En Java 8, ce problème a été résolu en utilisant la méthode par défaut.

Par exemple, l'interfaceCollection n'a pas de déclaration de méthodeforEach. Ainsi, l'ajout d'une telle méthode ne ferait que casser l'API de collections entière.

Java 8 introduit la méthode par défaut pour que l'interfaceCollection puisse avoir une implémentation par défaut de la méthodeforEach sans que les classes implémentant cette interface l'implémentent.

Q2. Le code suivant sera-t-il compilé?

@FunctionalInterface
public interface Function2 {
    public V apply(T t, U u);

    default void count() {
        // increment counter
    }
}

Yes. Le code sera compilé car il suit la spécification d'interface fonctionnelle consistant à ne définir qu'une seule méthode abstraite. La deuxième méthode,count, est une méthode par défaut qui n'augmente pas le nombre de méthodes abstraites.

7. Expressions Lambda

Q1. Qu'est-ce qu'une expression Lambda et à quoi sert-elle

En termes très simples, une expression lambda est une fonction qui peut être référencée et transmise en tant qu’objet.

Les expressions Lambda introduisent le traitement de style fonctionnel en Java et facilitent l'écriture de code compact et facile à lire.

Pour cette raison, les expressions lambda sont un remplacement naturel des classes anonymes en tant qu'arguments de méthode. L'une de leurs principales utilisations est de définir des implémentations en ligne d'interfaces fonctionnelles.

Q2. Expliquer la syntaxe et les caractéristiques d'une expression Lambda

Une expression lambda est composée de deux parties: la partie paramètre et la partie expressions séparées par une flèche comme indiqué ci-dessous:

params -> expressions

Toute expression lambda présente les caractéristiques suivantes:

  • Optional type declaration - lors de la déclaration des paramètres sur le côté gauche du lambda, nous n'avons pas besoin de déclarer leurs types car le compilateur peut les déduire de leurs valeurs. Doncint param → … etparam →… sont tous valides

  • Optional parentheses - lorsqu'un seul paramètre est déclaré, nous n'avons pas besoin de le placer entre parenthèses. Cela signifie queparam → … et(param) → … sont tous valides. Mais lorsque plusieurs paramètres sont déclarés, des parenthèses sont requises

  • Optional curly braces - lorsque la partie expressions n'a qu'une seule instruction, il n'y a pas besoin d'accolades. Cela signifie queparam – > statement etparam – > \{statement;} sont tous valides. Mais les accolades sont nécessaires quand il y a plus d'une déclaration

  • Optional return statement - lorsque l'expression renvoie une valeur et qu'elle est entourée d'accolades, nous n'avons pas besoin d'une instruction return. Cela signifie que(a, b) – > \{return a+b;} et(a, b) – > \{a+b;} sont tous deux valides

Pour en savoir plus sur les expressions Lambda, suivezthis link etthis one.

8. Nashorn Javascript

Q1. Qu'est-ce que Nashorn dans Java8?

Nashorn est le nouveau moteur de traitement Javascript pour la plate-forme Java livrée avec Java 8. Jusqu'en JDK 7, la plate-forme Java utilisait Mozilla Rhino dans le même but. en tant que moteur de traitement Javascript.

Nashorn offre une meilleure conformité avec la spécification JavaScript normalisée ECMA et de meilleures performances d'exécution que son prédécesseur.

Q2. Qu'est-ce que JJS?

Dans Java 8,jjs est le nouvel exécutable ou outil de ligne de commande utilisé pour exécuter du code Javascript sur la console.

9. Ruisseaux

Q1. Qu'est-ce qu'un flux? En quoi cela diffère-t-il d'une collection?

En termes simples, un flux est un itérateur dont le rôle est d’accepter un ensemble d’actions à appliquer à chacun des éléments qu’il contient.

The stream représente une séquence d'objets provenant d'une source telle qu'une collection, qui prend en charge les opérations d'agrégation. Ils ont été conçus pour rendre le traitement des collections simple et concis. Contrairement aux collections, la logique d'itération est implémentée à l'intérieur du flux, nous pouvons donc utiliser des méthodes commemap etflatMap pour effectuer un traitement déclaratif.

Une autre différence est que l'APIStream est fluide et permet le pipelining:

int sum = Arrays.stream(new int[]{1, 2, 3})
  .filter(i -> i >= 2)
  .map(i -> i * 3)
  .sum();

Une autre distinction importante par rapport aux collections est que les flux sont par nature chargés et traités paresseux.

Q2. Quelle est la différence entre les opérations intermédiaires et les opérations terminales?

Les opérations de flux sont combinées dans des pipelines pour traiter les flux. Toutes les opérations sont soit intermédiaires, soit terminales.

Les opérations intermédiaires sont les opérations qui renvoientStream lui-même permettant des opérations supplémentaires sur un flux.

Ces opérations sont toujours paresseuses, c.-à-d. ils ne traitent pas le flux sur le site de l'appel, une opération intermédiaire ne peut traiter des données que lorsqu'il y a une opération de terminal. Certaines des opérations intermédiaires sontfilter,map etflatMap.

Les opérations de terminal mettent fin au pipeline et lancent le traitement du flux. Le flux passe par toutes les opérations intermédiaires lors de l'appel d'opération du terminal. Les opérations du terminal incluentforEach,reduce, Collect etsum.

Pour faire passer ce message à la maison, examinons un exemple d'effets secondaires:

public static void main(String[] args) {
    System.out.println("Stream without terminal operation");

    Arrays.stream(new int[] { 1, 2, 3 }).map(i -> {
        System.out.println("doubling " + i);
        return i * 2;
    });

    System.out.println("Stream with terminal operation");
        Arrays.stream(new int[] { 1, 2, 3 }).map(i -> {
            System.out.println("doubling " + i);
            return i * 2;
    }).sum();
}

La sortie sera comme suit:

Stream without terminal operation
Stream with terminal operation
doubling 1
doubling 2
doubling 3

Comme vous pouvez le constater, les opérations intermédiaires ne sont déclenchées qu’une opération de terminal.

Q3. Quelle est la différence entre le fonctionnement du fluxMap etflatMap?

Il existe une différence de signature entremap etflatMap. D'une manière générale, une opérationmap encapsule sa valeur de retour dans son type ordinal alors queflatMap ne le fait pas.

Par exemple, dansOptional, une opérationmap renverrait le typeOptional<String> tandis queflatMap renverrait le typeString.

Ainsi, après le mappage, il faut dérouler (lire "aplatir") l'objet pour récupérer la valeur, alors qu'après le mappage à plat, il n'est plus nécessaire car l'objet est déjà aplati. Le même concept est appliqué au mappage et au mappage plat enStream.

Lesmap etflatMap sont des opérations de flux intermédiaires qui reçoivent une fonction et appliquent cette fonction à tous les éléments d'un flux.

La différence est que pour lesmap, cette fonction renvoie une valeur, mais pour lesflatMap, cette fonction renvoie un flux. L'opérationflatMap «aplatit» les flux en un seul.

Voici un exemple dans lequel nous prenons une carte des noms d'utilisateurs et des listes de téléphones et nous la «réduisons» à une liste de téléphones de tous les utilisateurs utilisantflatMap:

Map> people = new HashMap<>();
people.put("John", Arrays.asList("555-1123", "555-3389"));
people.put("Mary", Arrays.asList("555-2243", "555-5264"));
people.put("Steve", Arrays.asList("555-6654", "555-3242"));

List phones = people.values().stream()
  .flatMap(Collection::stream)
    .collect(Collectors.toList());

Q4. Qu'est-ce que Stream Pipelining dans Java 8?

Le pipeline pipeline est le concept de chaînage des opérations. Cela se fait en divisant les opérations pouvant se produire sur un flux en deux catégories: les opérations intermédiaires et les opérations de terminal.

Chaque opération intermédiaire renvoie une instance de Stream elle-même lors de son exécution, un nombre arbitraire d'opérations intermédiaires peut donc être configuré pour traiter les données formant un pipeline de traitement.

Il doit alors y avoir une opération de terminal qui renvoie une valeur finale et termine le pipeline.

10. API de date et d'heure Java 8

Q1. Parlez-nous de la nouvelle API de date et d'heure dans Java 8

Un problème de longue date pour les développeurs Java est le support inadéquat pour les manipulations de date et heure requises par les développeurs ordinaires.

Les classes existantes telles quejava.util.Date etSimpleDateFormatter ne sont pas thread-safe, ce qui entraîne des problèmes potentiels de concurrence d'accès pour les utilisateurs.

La mauvaise conception des API est également une réalité dans l'ancienne API de données Java. Voici juste un exemple rapide: les années enjava.util.Date commencent à 1900, les mois commencent à 1 et les jours commencent à 0, ce qui n'est pas très intuitif.

Ces problèmes et plusieurs autres ont conduit à la popularité des bibliothèques tierces de date et d'heure, telles que Joda-Time.

Afin de résoudre ces problèmes et de fournir un meilleur support dans JDK, une nouvelle API de date et d'heure, qui est exempte de ces problèmes, a été conçue pour Java SE 8 sous le packagejava.time.

11. Conclusion

Dans cet article, nous avons exploré quelques questions très importantes pour les questions d'entretien technique avec un biais sur Java 8. Cette liste n’est en aucun cas exhaustive, elle ne contient que des questions qui, selon nous, devraient figurer dans chaque nouvelle fonctionnalité de Java 8.

Même si vous venez de démarrer, l’ignorance de Java 8 n’est pas une bonne façon de procéder lors d’une interview, en particulier lorsque Java apparaît fortement sur votre CV. Il est donc important que vous preniez le temps de comprendre les réponses à ces questions et éventuellement de faire plus de recherches.

Bonne chance dans votre interview.