JavaRush /Blog Java /Random-FR /Noyau Java. Questions pour un entretien, partie 3
Vadim625
Niveau 27

Noyau Java. Questions pour un entretien, partie 3

Publié dans le groupe Random-FR
Dans les deux articles précédents, nous avons abordé certaines questions importantes qui vous sont le plus souvent posées lors des entretiens. Il est temps de passer à autre chose et d'examiner le reste des questions.
Noyau Java.  Questions d'entretien, parties 3 à 1

Copie profonde et copie superficielle

Une copie exacte de l'original est son clone. En Java, cela signifie être capable de créer un objet avec une structure similaire à l'objet d'origine. La méthode clone()fournit cette fonctionnalité. La copie superficielle copie le moins d'informations possible. Par défaut, le clonage en Java est superficiel, c'est-à-dire Object classne connaît pas la structure de la classe qu'il copie. Lors du clonage, la JVM effectue les opérations suivantes :
  1. Si une classe ne contient que des membres de types primitifs, alors une toute nouvelle copie de l'objet sera créée et une référence à cet objet sera renvoyée.
  2. Si une classe contient non seulement des membres de types primitifs, mais également des membres de tout autre type de classe, alors les références aux objets de ces classes sont copiées. Les deux objets auront donc les mêmes références.
La copie profonde duplique tout. La copie profonde consiste en deux collections, dont l'une duplique tous les éléments de la collection originale. Nous voulons faire une copie de telle sorte que toute modification apportée à un élément de la copie n'affectera pas la collection originale. Le clonage profond nécessite les règles suivantes :
  1. Il n'est pas nécessaire de copier les données primitives séparément ;
  2. Toutes les classes membres de la classe d'origine doivent prendre en charge le clonage. Pour chaque membre de la classe, il doit être appelé super.clone()lorsque la méthode est substituée clone();
  3. Si un membre d'une classe ne prend pas en charge le clonage, alors dans la méthode clone, vous devez créer une nouvelle instance de cette classe et copier chacun de ses membres avec tous les attributs dans un nouvel objet de classe, un à la fois.
En savoir plus sur le clonage ici

Qu'est-ce que la synchronisation ? Verrouillage au niveau de l'objet et verrouillage au niveau de la classe ?

La synchronisation fait référence au multithreading. Un bloc de code synchronisé ne peut être exécuté que par un seul thread à la fois. Java vous permet de traiter plusieurs threads simultanément. Cela peut amener deux threads ou plus à vouloir accéder au même champ. La synchronisation permet d'éviter les erreurs de mémoire qui se produisent lorsque les ressources mémoire sont utilisées de manière incorrecte. Lorsqu'une méthode est déclarée synchronisée, le thread conserve son moniteur. Si un autre thread tente d'accéder à une méthode synchronisée à ce moment-là, le thread est bloqué et attend que le moniteur se libère. La synchronisation en Java est réalisée avec le mot-clé spécial synchronisé . Vous pouvez ainsi marquer des blocs ou des méthodes individuels dans votre classe. Le mot-clé synchronisé ne peut pas être utilisé conjointement avec des variables ou des attributs de classe. Le verrouillage au niveau de l'objet est un mécanisme permettant de synchroniser une méthode non statique ou un bloc de code non statique afin qu'un seul thread puisse exécuter le bloc de code sur une instance donnée de la classe. Cela doit toujours être fait pour sécuriser le thread de l'instance de classe. Le verrouillage au niveau de la classe empêche plusieurs threads d'entrer dans un bloc synchronisé pour toutes les instances disponibles de la classe. Par exemple, s'il existe 100 instances de la classe DemoClass, alors un seul thread pourra exécuter demoMethod() en utilisant l'une des variables à un moment donné. Cela doit toujours être fait pour garantir la sécurité des threads statiques. Apprenez-en davantage sur la synchronisation ici.

Quelle est la différence entre sleep() et wait() ?

Sleep()est une méthode utilisée pour retarder le processus de quelques secondes. Dans le cas de wait(), le thread est dans un état d'attente jusqu'à ce que nous appelions la méthode notify()ou notifyAll(). La principale différence est qu'il wait()libère le verrouillage du moniteur alors qu'il sleep()ne le libère pas. Wait()utilisé pour les applications multithread, sleep()utilisé simplement pour suspendre l'exécution du thread. Thread.sleep()met le thread actuel dans l'état "Non exécutable" pendant un certain temps. Le thread enregistre l’état du moniteur avant l’appel de cette méthode. Si un autre thread appelle t.interrupt(), le thread qui s'est « endormi » se réveillera. Notez qu'il sleep()s'agit d'une méthode statique, ce qui signifie qu'elle affecte toujours le thread actuel (celui qui exécute la méthode sleep()). Une erreur courante consiste à appeler t.sleep()"où tse trouve un autre fil de discussion" ; même lorsque le thread actuel qui a appelé la méthode sleep()n'est pas tun thread. Object.wait()envoie le thread actuel dans l'état "Non exécutable" pendant un certain temps, tout comme sleep(), mais avec quelques nuances. Wait()appelé sur un objet, pas sur un thread ; nous appelons cet objet « objet de verrouillage ». Avant d'appeler lock.wait(), le thread actuel doit être synchronisé avec « l'objet verrouillé » ; wait()après cela, il libère ce verrou et ajoute le fil de discussion à la « liste d'attente » associée à ce verrou. Plus tard, un autre thread peut se synchroniser avec le même objet de verrouillage et appeler le lock.notify(). Cette méthode "réveillera" le thread d'origine, qui est toujours en attente. En principe, wait()/ notify()peut être comparé à sleep()/ interrupt(), seul le thread actif n'a pas besoin d'un pointeur direct vers le thread en veille, il a seulement besoin de connaître l'objet de verrouillage partagé. Lisez la différence détaillée ici.

Est-il possible d'attribuer null à une variable de référence ?

Non tu ne peux pas. En Java, le côté gauche de l'opérateur d'affectation doit être une variable. "This" est un mot-clé spécial qui donne toujours l'instance actuelle de la classe. Ce n'est pas n'importe quelle variable. De même, null ne peut pas être attribué à une variable à l’aide du mot-clé « super » ou de tout autre mot-clé similaire.

Quelle est la différence entre && et & ?

&- au niveau du bit et &&- logiquement.
  1. &évalue les deux côtés de l’opération ;
  2. &&évalue le côté gauche de l’opération. Si c'est vrai, il continue d'évaluer le côté droit.
Regardez ici pour une compréhension plus profonde.

Comment remplacer les méthodes equals() et hachCode() ?

hashCode()et equals()les méthodes sont définies dans la classe Object, qui est la classe parent des objets Java. Pour cette raison, tous les objets Java héritent de l'implémentation par défaut des méthodes. La méthode hashCode()est utilisée pour obtenir un entier unique pour un objet donné. Cet entier est utilisé pour déterminer l'emplacement d'un objet lorsque cet objet doit être stocké, par exemple pour HashTable. Par défaut, hashCode()renvoie integerune représentation de l'adresse de l'emplacement mémoire où l'objet est stocké. La méthode equls(), comme son nom l'indique, permet de tester simplement si deux objets sont égaux. L'implémentation par défaut vérifie les références d'objet pour voir si elles sont égales. Vous trouverez ci-dessous des directives importantes pour recharger ces méthodes :
  1. Utilisez toujours les mêmes attributs d'objet lors de la génération hashCode()de et equals();
  2. Symétrie. Ceux. xs'il renvoie true pour certains objets y x.equals(y), alors il y.equals(x)doit renvoyer true ;
  3. Réflexivité. Car tout objet x x.equals(x)doit renvoyer true ;
  4. Cohérence. Pour tous les objets xet y x.equals(y)renvoie la même chose si les informations utilisées dans les comparaisons ne changent pas ;
  5. Transitivité. Pour tous les objets x, yet z, s'il x.equals(y)renvoie true et y.equals(z)renvoie true, alors il x.equals(z)doit renvoyer true ;
  6. Chaque fois qu'une méthode est appelée sur le même objet lors de l'exécution de l'application, elle doit renvoyer le même numéro sauf si les informations utilisées changent. hashCodepeut renvoyer des valeurs différentes pour des objets identiques dans différentes instances d'application ;
  7. Si deux objets sont égaux, selon equals, alors ils hashCodedoivent renvoyer les mêmes valeurs ;
  8. L’exigence inverse est facultative. Deux objets inégaux peuvent renvoyer le même hashCode. Cependant, pour améliorer les performances, il est préférable que différents objets renvoient des codes différents.
Lisez des faits intéressants sur ces méthodes ici.

Parlez-nous des modificateurs d'accès

Les classes, champs, constructeurs et méthodes Java peuvent avoir l'un des quatre modificateurs d'accès différents : private Si une méthode ou une variable est marquée comme private , alors seul le code de la même classe peut accéder à la variable ou appeler la méthode. Le code à l’intérieur des sous-classes ne peut pas accéder à une variable ou à une méthode, ni à partir d’une autre classe. Le modificateur d'accès privé est le plus souvent utilisé pour les constructeurs, les méthodes et les variables. default Le modificateur d'accès par défaut est déclaré si le modificateur n'est pas spécifié du tout. Ce modificateur signifie que l'accès aux champs, constructeurs et méthodes d'une classe donnée peut être obtenu par du code à l'intérieur de la classe elle-même, du code à l'intérieur des classes du même package. Les sous-classes ne peuvent pas accéder aux méthodes et aux variables membres d'une superclasse si elles sont déclarées comme default , sauf si la sous-classe se trouve dans le même package que la superclasse. protected Le modificateur protected fonctionne de la même manière que default , sauf que les sous-classes peuvent également accéder aux méthodes et variables protégées de la superclasse. Cette affirmation est vraie même si la sous-classe ne se trouve pas dans le même package que la superclasse. public Le modificateur d'accès public signifie que tout le code peut accéder à la classe, à ses variables, constructeurs ou méthodes, quel que soit l'endroit où se trouve ce code. Noyau Java.  Questions pour un entretien, partie 3 - 2

Qu'est-ce qu'un éboueur ? Pouvons-nous l'appeler ?

Le garbage collection est une fonctionnalité de gestion automatique de la mémoire dans de nombreux langages de programmation modernes, tels que Java et les langages de NET.Framework. Les langages qui utilisent le garbage collection interprètent souvent le garbage collection dans une machine virtuelle telle que la JVM. Le garbage collection a deux objectifs : toute mémoire inutilisée doit être libérée et la mémoire ne doit pas être libérée si le programme l'utilise toujours. Pouvez-vous exécuter le garbage collection manuellement ? Non, System.gc()cela vous donne autant d'accès que possible. La meilleure option est d'appeler la méthode System.gc(), qui indiquera au garbage collector qu'elle doit s'exécuter. Il n'y a aucun moyen de l'exécuter immédiatement puisque le garbage collector n'est pas déterministe. De plus, selon la documentation, OutOfMemoryErroril ne sera pas transmis si la machine virtuelle ne parvient pas à libérer de la mémoire après un garbage collection complet. Apprenez-en davantage sur le ramasse-miettes ici.

Que signifie le mot clé natif ? Expliquer en détail

Le mot-clé natif permet d'indiquer que la méthode est implémentée dans un langage de programmation autre qu'un fichier Java. Des méthodes natives ont été utilisées dans le passé. Dans les versions actuelles de Java, cela est moins souvent nécessaire. Actuellement, des méthodes natives sont nécessaires lorsque :
  1. Vous devez appeler une bibliothèque depuis Java écrite dans un autre langage.
  2. Vous devez accéder à des ressources système ou matérielles accessibles uniquement à l'aide d'un autre langage (généralement C). En fait, de nombreuses fonctions système qui interagissent avec l'ordinateur réel (comme les disques ou les données réseau) ne peuvent être appelées que par la méthode native.
Les inconvénients de l’utilisation de bibliothèques de méthodes natives sont également importants :
  1. JNI/JNA peut déstabiliser la JVM, surtout si vous essayez de faire quelque chose de complexe. Si votre méthode native fait quelque chose de mal, il est possible que la JVM plante. De plus, de mauvaises choses peuvent arriver si votre méthode native est appelée à partir de plusieurs threads. Et ainsi de suite.
  2. Il est plus difficile de déboguer un programme avec du code natif .
  3. Le code natif nécessite une construction séparée de frameworks, ce qui peut créer des problèmes de portage vers d'autres plates-formes.

Qu'est-ce que la sérialisation ?

En informatique, dans le contexte du stockage et de la transmission de données, la sérialisation est le processus de traduction d'une structure de données ou de l'état d'un objet dans un format pouvant être stocké puis récupéré dans un autre environnement informatique. Après avoir reçu une série de bits, ils sont recalculés selon le format de sérialisation et peuvent être utilisés pour créer un clone sémantiquement identique de l'objet d'origine. Java fournit une sérialisation automatique, qui nécessite que l'objet implémente l'interface java.io.Serializable. L'implémentation de l'interface marque la classe comme « sérialisable ». L'interface java.io.Serializing n'a pas de méthodes de sérialisation, mais la classe sérialisable peut éventuellement définir des méthodes qui seront appelées dans le cadre du processus de sérialisation/désérialisation. Lorsque vous apportez des modifications aux classes, vous devez déterminer lesquelles seront ou non compatibles avec la sérialisation. Vous pouvez lire les instructions complètes ici. Je vais donner les points les plus importants : Modifications incompatibles :
  1. Supprimer un champ ;
  2. Déplacer une classe vers le haut ou vers le bas dans la hiérarchie ;
  3. Changer un champ non statique en statique ou non transitoire en transitoire ;
  4. Modification du type de données primitif déclaré ;
  5. Changer la méthode WriteObjectsoit ReadObjectpour qu'ils n'écrivent ni ne lisent plus de champs par défaut ;
  6. Changer de classe Serializableou Externalizablevice versa ;
  7. Changer une classe enum en une classe non-enum ou vice versa ;
  8. Suppression Serializablede ouExternalizable ;
  9. Ajout writeReplaced'une readResolveméthode à une classe.
Modifications compatibles :
  1. Ajout de champs ;
  2. Ajouter/supprimer des classes ;
  3. Ajout de méthodes WriteObject/ReadObject[les méthodes defaultReadObjectou defaultWriteObjectdoivent être appelées au début] ;
  4. Méthodes de suppressionWriteObject/ReadObject ;
  5. Ajout java.io.Serializable;
  6. Modification de l'accès au champ ;
  7. Changer un champ statique en non-statique ou transitoire en non-transient .
Liens vers les parties précédentes : Java Core. Questions d'entretien, partie 1 Java Core. Questions d'entretien, partie 2 Article original Bonnes études !
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION