Questions d’entretien d’embauche et d’initialisation de classe Java

1. Introduction

La structure et l’initialisation des classes sont les bases avec lesquelles tout programmeur Java devrait être familiarisé. Cet article fournit des réponses à certaines des questions de l’entrevue sur le sujet que vous pourriez rencontrer.

Q1. Décrivez la signification du mot clé final lorsqu’il est appliqué à une classe, une méthode, un champ ou une variable locale.

Le mot clé final a plusieurs significations différentes lorsqu’il est appliqué à différentes constructions de langage:

  • Une classe final est une classe qui ne peut pas être sous-classée

  • Une méthode final est une méthode qui ne peut pas être remplacée dans les sous-classes.

  • Un champ final est un champ qui doit être initialisé dans le

le constructeur ou le bloc d’initialisation et ne peut plus être modifié par la suite ** Une variable final est une variable qui peut être affectée (et doit être

assigné) une seule fois et n’est jamais modifié après cela

Q2. Qu’est-ce qu’une méthode default ?

Avant Java 8, les interfaces ne pouvaient avoir que des méthodes abstraites, c’est-à-dire

méthodes sans corps. À partir de Java 8, les méthodes d’interface peuvent avoir une implémentation par défaut. Si une classe d’implémentation ne substitue pas cette méthode, l’implémentation par défaut est utilisée. De telles méthodes sont convenablement marquées avec un mot clé default .

L’un des cas d’utilisation les plus importants d’une méthode default consiste à ajouter une méthode à une interface existante. Si vous ne marquez pas cette méthode d’interface comme étant default , toutes les implémentations existantes de cette interface se briseront. L’ajout d’une méthode avec une implémentation default garantit la compatibilité binaire du code hérité avec la nouvelle version de cette interface.

Un bon exemple de ceci est l’interface Iterator qui permet à une classe d’être la cible de la boucle for-each. Cette interface est apparue pour la première fois en Java 5, mais en Java 8, elle a reçu deux méthodes supplémentaires, forEach et spliterator . Elles sont définies comme méthodes par défaut avec les implémentations et n’empêchent donc pas la compatibilité ascendante:

public interface Iterable<T> {

    Iterator<T> iterator();

    default void forEach(Consumer<? super T> action) {/**  ** /}

    default Spliterator<T> spliterator() {/**  ** /}
}

Q3. Que sont les membres de la classe static ?

Les champs et les méthodes d’une classe ne sont pas liés à une instance spécifique d’une classe. Au lieu de cela, ils sont liés à l’objet de classe lui-même.

L’appel d’une méthode static ou l’adressage d’un champ static est résolu au moment de la compilation car, contrairement aux méthodes d’instance et aux champs, nous n’avons pas besoin de parcourir la référence et de déterminer un objet réel auquel nous faisons référence.

Q4. Une classe peut-elle être déclarée abstraite si elle n’a aucun membre abstrait? Quel pourrait être le but d’une telle classe?

Oui, une classe peut être déclarée abstract même si elle ne contient aucun membre abstract . En tant que classe abstraite, elle ne peut pas être instanciée, mais elle peut servir d’objet racine d’une hiérarchie, fournissant des méthodes pouvant être utiles à ses implémentations.

Q5. Qu’est-ce que le chaînage des constructeurs?

Le chaînage de constructeurs est un moyen de simplifier la construction d’objets en fournissant plusieurs constructeurs qui s’appellent les uns après les autres.

Le constructeur le plus spécifique peut prendre tous les arguments possibles et peut être utilisé pour la configuration d’objet la plus détaillée. Un constructeur moins spécifique peut appeler le constructeur plus spécifique en fournissant certains de ses arguments avec des valeurs par défaut. Au sommet de la chaîne, un constructeur sans argument pourrait instancier un objet avec des valeurs par défaut.

Voici un exemple avec une classe qui modélise une remise en pourcentage disponible dans un certain nombre de jours. Les valeurs par défaut de 10% et 2 jours sont utilisées si nous ne les spécifions pas avec un constructeur sans argument:

public class Discount {

    private int percent;

    private int days;

    public Discount() {
        this(10);
    }

    public Discount(int percent) {
        this(percent, 2);
    }

    public Discount(int percent, int days) {
        this.percent = percent;
        this.days = days;
    }

}

Q6. Qu’est-ce que le dépassement et la surcharge des méthodes? Comment sont-ils différents?

Le remplacement d’une méthode est effectué dans une sous-classe lorsque vous définissez une méthode avec la même signature que dans la superclasse. Cela permet au moteur d’exécution de choisir une méthode en fonction du type d’objet sur lequel vous appelez la méthode. Les méthodes toString , equals et hashCode sont remplacées assez souvent dans les sous-classes.

La surcharge d’une méthode se produit dans la même classe. La surcharge se produit lorsque vous créez une méthode avec le même nom mais avec différents types ou nombre d’arguments. Cela vous permet d’exécuter un certain code en fonction des types d’arguments que vous fournissez, tandis que le nom de la méthode reste le même.

Voici un exemple de surcharge dans la classe abstraite java.io.Writer .

Les méthodes suivantes sont toutes deux nommées write , mais l’une d’entre elles reçoit un int tandis qu’une autre reçoit un tableau char .

public abstract class Writer {

    public void write(int c) throws IOException {
       //...
    }

    public void write(char cbuf[]) throws IOException {
       //...
    }

}

Q7. Pouvez-vous remplacer une méthode static ?

Non, tu ne peux pas. Par définition, vous ne pouvez remplacer une méthode que si son implémentation est déterminée au moment de l’exécution par le type de l’instance réelle (processus appelé recherche de méthode dynamique). L’implémentation de la méthode static est déterminée au moment de la compilation en utilisant le type de la référence. Par conséquent, une substitution n’aurait pas beaucoup de sens. Bien que vous puissiez ajouter à la sous-classe une méthode static avec exactement la même signature que dans la superclasse, ceci n’est techniquement pas prioritaire.

Q8. Qu’est-ce qu’une classe immuable et comment pouvez-vous en créer une?

Une instance d’une classe immuable ne peut pas être modifiée après sa création.

Par changement, nous entendons une mutation de l’état en modifiant les valeurs des champs de l’instance. Les classes immuables présentent de nombreux avantages: elles sont thread-safe et il est beaucoup plus facile de raisonner à leur sujet lorsque vous n’avez pas d’état mutable à prendre en compte.

Pour rendre une classe immuable, vous devez vous assurer que:

  • Tous les champs doivent être déclarés private et final ; cela en déduit que

ils devraient être initialisés dans le constructeur et ne jamais être modifiés puisque; ** La classe ne devrait pas avoir de setters ou d’autres méthodes qui muent le

valeurs des champs; ** Tous les champs de la classe qui ont été passés via le constructeur doivent soit

être également immuable, ou leurs valeurs doivent être copiées avant le champ initialisation (sinon on pourrait changer l’état de cette classe en s’accrocher à ces valeurs et les modifier); ** Les méthodes de la classe ne doivent pas être écrasables; soit toutes les méthodes

devrait être final , ou le constructeur devrait être private et uniquement appelé via la méthode static factory.

Q9. Comment comparez-vous deux valeurs enum : avec equals () ou avec == ?

En fait, vous pouvez utiliser les deux. Les valeurs de enum sont des objets, elles peuvent donc être comparées avec equals () , mais elles sont également implémentées sous la forme de constantes static , vous pouvez donc les comparer avec == .

C’est principalement une question de style de code, mais si vous souhaitez économiser de l’espace (et éviter éventuellement un appel de méthode inutile), vous devez comparer les énumérations avec == .

Q10. Qu’est-ce qu’un bloc d’initialisation? Qu’est-ce qu’un bloc d’initialisation static ?

Un bloc d’initialisation est un bloc de code entouré de balises dans l’étendue de la classe, qui est exécuté lors de la création de l’instance. Vous pouvez l’utiliser pour initialiser des champs avec quelque chose de plus complexe que les monolithes d’initialisation sur place.

En fait, le compilateur copie simplement ce bloc à l’intérieur de chaque constructeur. Il s’agit donc d’un bon moyen d’extraire le code courant de tous les constructeurs.

Un bloc d’initialisation statique est un bloc de code entouré de courbes et précédé du modificateur static . Il est exécuté une fois pendant le chargement de la classe et peut être utilisé pour l’initialisation de champs statiques ou pour certains effets secondaires.

Q11. Qu’est-ce qu’une interface de marqueur? Quels sont les exemples notables d’interfaces de marqueurs en Java?

Une interface de marqueur est une interface sans aucune méthode. Il est généralement implémenté par une classe ou étendu par une autre interface pour signifier une certaine propriété. Les interfaces de marqueur les plus connues dans la bibliothèque Java standard sont les suivantes:

  • Serializable est utilisé pour exprimer explicitement que cette classe peut être

sérialisé; ** Cloneable permet le clonage d’objets à l’aide de la méthode clone (sans

Cloneable interface en place, cette méthode jette un CloneNotSupportedException ); ** Remote est utilisé dans RMI pour spécifier une interface avec laquelle les méthodes peuvent être

appelé à distance.

Q12. Qu’est-ce qu’un singleton et comment peut-il être implémenté en Java?

Singleton est un modèle de programmation orientée objet. Une classe singleton ne peut avoir qu’une seule instance, généralement visible et accessible globalement.

Il existe plusieurs façons de créer un singleton en Java. Voici l’exemple le plus simple avec un champ static initialisé sur place. L’initialisation est sécurisée pour les threads car les champs static sont garantis pour être initialisés de manière sécurisée pour les threads. Le constructeur est private , il n’y a donc aucun moyen pour le code externe de créer plus d’une instance de la classe.

public class SingletonExample {

    private static SingletonExample instance = new SingletonExample();

    private SingletonExample() {}

    public static SingletonExample getInstance() {
        return instance;
    }
}

Mais cette approche pourrait avoir un sérieux inconvénient: l’instance serait instanciée lors du premier accès à cette classe. Si l’initialisation de cette classe est une opération lourde et que nous aimerions probablement la différer jusqu’à ce que l’instance soit réellement nécessaire (voire jamais), mais en même temps, gardez-la thread-safe. Dans ce cas, nous devrions utiliser une technique connue sous le nom de verrouillage double vérifié .

Q13. Qu’est-ce qu’un var-arg? Quelles sont les restrictions sur un var-arg? Comment pouvez-vous l’utiliser dans le corps de la méthode?

Var-arg est un argument de longueur variable pour une méthode. Une méthode peut avoir un seul var-arg, et il doit figurer en dernier dans la liste des arguments. Il est spécifié en tant que nom de type suivi de points de suspension et d’un nom d’argument. Dans le corps de la méthode, var-arg est utilisé en tant que tableau du type spécifié.

Voici un exemple tiré de la bibliothèque standard - la méthode Collections.addAll qui reçoit une collection, un nombre variable d’éléments et ajoute tous les éléments à la collection:

public static <T> boolean addAll(
  Collection<? super T> c, T... elements) {
    boolean result = false;
    for (T element : elements)
        result |= c.add(element);
    return result;
}

Q14. Pouvez-vous accéder à une méthode surchargée d’une super-classe? Pouvez-vous accéder à une méthode substituée d’une super-super-classe de manière similaire?

Pour accéder à une méthode substituée d’une super-classe, vous pouvez utiliser le mot clé super . Mais vous n’avez pas le même moyen d’accéder à la méthode surchargée d’une super-classe.

Par exemple, à partir de la bibliothèque standard, la classe LinkedHashMap étend HashMap et réutilise principalement ses fonctionnalités, en ajoutant une liste liée à ses valeurs pour préserver l’ordre des itérations. LinkedHashMap réutilise la méthode clear de sa super-classe, puis efface les références de tête et de queue de sa liste liée:

public void clear() {
    super.clear();
    head = tail = null;
}

Suivant "

  • "** Précédent