JavaRush /Blog Java /Random-FR /Analyse des questions et réponses des entretiens pour dév...

Analyse des questions et réponses des entretiens pour développeur Java. Partie 4

Publié dans le groupe Random-FR
Bonjour à tous, aujourd'hui je continue d'analyser plus de 250 questions d'entretien pour les développeurs Java. Analyse des questions et réponses des entretiens pour développeur Java.  Partie 4 - 1Parties précédentes de l'analyse : première , deuxième , troisième . Alors continuons.

29. Est-il possible d'utiliser le retour dans un constructeur ?

Vous pouvez, mais sans la valeur de retour à droite de return . Autrement dit, vous pouvez utiliser return ; comme construction auxiliaire lors des calculs dans le constructeur afin de terminer (interrompre) de toute urgence l'exécution de code supplémentaire et de terminer l'initialisation de l'objet. Par exemple, nous avons une classe Cat , et si Cat est sans abri - isHomeless = true , nous devons terminer l'initialisation et ne pas remplir d'autres champs (après tout, ils nous sont inconnus, puisque le chat est sans abri) :

public Cat(int age, String name, boolean isHomeless) {
   if (isHomeless){
       this.isHomeless = isHomeless;
       return;
   }
   this.isHomeless = isHomeless;
   this.age = age;
   this.name = name;
}
Mais lorsqu'il s'agit de valeurs spécifiques, un constructeur ne peut pas utiliser return pour renvoyer une valeur car :
  • lors de la déclaration d'un constructeur, vous n'aurez rien qui ressemble à un type de retour ;
  • Généralement, le constructeur est appelé implicitement lors de l'instanciation ;
  • Un constructeur n'est pas une méthode : c'est un mécanisme distinct dont le seul but est d'initialiser les variables d'instance, et l' opérateur new est responsable de la création d'un objet .
Analyse des questions et réponses des entretiens pour développeur Java.  Partie 4 - 2

30. Est-il possible de lever une exception depuis un constructeur ?

Les constructeurs gèrent les exceptions exactement de la même manière que les méthodes. Et si les méthodes nous permettent de lever des exceptions en écrivant throws <ExceptionType> dans l'en-tête de la méthode , alors le constructeur nous permet de le faire, et également lors de l'héritage et de la définition d'un constructeur héritier, nous pouvons étendre le type d'exception. Par exemple, IOException -> Exception (mais pas l'inverse). Comme exemple de levée d'une exception par un constructeur, prenons la classe Cat . Disons que lors de sa création, nous souhaitons saisir le nom et l'âge depuis la console :

public Cat() throws IOException {
   BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
   this.name = reader.readLine();
   this.age = Integer.parseInt(reader.readLine());
}
Puisque reader.readLine() renvoie une IOException, nous la spécifions dans l'en-tête comme une exception levée possible.

31. De quels éléments se compose l'en-tête de classe ? Écrivez un exemple

En parlant des éléments qui composent l'en-tête de classe, regardons un petit schéma :
  • les éléments obligatoires seront entre parenthèses <>
  • facultatif - dans {}
{modificateur d'accès à la classe}{staticité de la classe}{finalité de la classe}{abstraction de la classe} <nom de classe>{héritage de la classe parent} {implémentation de l'interface} Donc, ce que nous avons : {class access modifier} - seuls les modificateurs publics et le modificateur d'accès manquant, c'est-à-dire default , sont disponibles pour la classe . {class static} - static est un modificateur qui indique que cette classe est statique, applicable uniquement aux classes internes (classes à l'intérieur d'autres classes). {finalité de la classe} - comme on s'en souvient, il s'agit du modificateur final , en présence duquel la classe devient non héritable (exemple de la boîte - String ). {class abstraction} - modifier - abstract , ce qui indique que cette classe peut avoir des méthodes non implémentées. Ce modificateur est en conflit avec le modificateur final , c'est-à-dire qu'un seul d'entre eux peut être dans l'en-tête de classe, car le modificateur abstrait implique que la classe donnée sera héritée et que ses parties abstraites seront implémentées. Et final indique qu'il s'agit de la version finale (finale) de la classe et qu'elle ne peut pas être héritée. En fait, utiliser les deux modificateurs en même temps serait absurde, et le compilateur ne nous permettra pas de le faire. <class> est un mot-clé obligatoire qui indique une déclaration de classe. <nom de classe> est un nom de classe simple, qui est l'identifiant d'une classe Java spécifique. Le nom de classe complet se compose du nom de package complet + . + nom de classe simple. {héritage de la classe parent} - spécifiant la classe parent (le cas échéant) à l'aide du mot-clé extends . Par exemple, .. étend ParentClass . {implémentation d'interface} - spécifiant les interfaces que cette classe implémente (le cas échéant) à l'aide du mot-clé Implements . Par exemple : ... implémente FirstInterface, SecondInterface ... Eh bien, comme exemple d'en-tête de classe, considérons l'en-tête de la classe Lion , qui hérite de Cat et implémente l' interface WildAnimal :

public final class Lion extends Cat implements WildAnimal
Analyse des questions et réponses des entretiens pour développeur Java.  Partie 4 - 3

32. De quels éléments se compose l'en-tête de la méthode ? Écrivez un exemple

Encore une fois, lorsque vous examinez les éléments qui composent un en-tête de méthode, considérez un petit diagramme où :
  • les composants obligatoires sont entre parenthèses <>
  • facultatif - dans {}
{modificateur d'accès}{méthode statique}{abstraction de la méthode}{finalité de la méthode}{modificateur de synchronisation} {modificateur natif}<valeur de retour><nom de la méthode> <(> {arguments de la méthode} <)>{exceptions levées} {modificateur d'accès } — tous les modificateurs d'accès sont disponibles pour la méthode : public , protected , default , private . {méthode statique} - static est un modificateur qui indique que cette méthode est statique, c'est-à-dire qu'elle est liée non pas à un objet, mais à une classe. {abstraction de méthode} est le modificateur abstrait , qui indique qu'il n'y a pas d'implémentation (corps) de la méthode. Pour un fonctionnement correct, vous avez également besoin d'un modificateur abstrait pour la classe dans laquelle la méthode est fournie. Comme dans l'en-tête de classe, ce modificateur entre en conflit avec le modificateur final , mais en plus, il entre également en conflit avec le modificateur static , car une méthode abstraite implique le remplacement de la méthode dans le descendant, et les méthodes statiques ne sont pas remplacées. {finalité de la méthode} - final - un modificateur indiquant que cette méthode ne peut pas être remplacée. {modificateur de synchronisation} - synchronisé - un modificateur qui signifie que cette méthode est protégée contre tout accès simultané à celle-ci à partir de différents threads. Si la méthode n'est pas statique, elle se ferme sur ce mutex de l'objet. Si la méthode est statique, elle se ferme sur le mutex de la classe actuelle. {modificateur natif} - natif - ce modificateur indique que la méthode est écrite dans un langage de programmation différent. <valeur de retour> est le type de valeur que la méthode doit renvoyer. S'il ne retourne rien, void . <nom de la méthode> est le nom de la méthode, son identifiant dans le système. Les {arguments de la méthode} sont les arguments (paramètres) que prend la méthode : ils sont nécessaires pour implémenter sa fonctionnalité. {exceptions jetables} - throwsExceptionType - une liste d'exceptions vérifiées que cette méthode peut lever. Et comme exemple d’en-tête de méthode, je vais donner ceci :

public static void main(String[] args) throws IOException

33. Créez un constructeur par défaut dans l'objet descendant s'il n'est pas défini dans l'objet de base (mais qu'un autre constructeur est défini)

Je ne comprends pas entièrement la question elle-même, mais cela signifie peut-être que, par exemple, dans le parent, nous avons un constructeur personnalisé :

public Cat(int age, String name) {
   this.age = age;
   this.name = name;
}
Par conséquent, dans la classe ancêtre, nous devons absolument définir un constructeur qui remplira (appellera) le constructeur parent :

public  class Lion extends Cat {
 
   public Lion(int age, String name) {
       super(age, name);
   }
}
Analyse des questions et réponses des entretiens pour développeur Java.  Partie 4 - 4

34. Quand le mot-clé this est-il utilisé ?

En Java, cela a deux significations différentes. 1. En référence à l'objet actuel, comme this.age = 9 . Autrement dit, this fait référence à l'objet sur lequel il a été appelé et auquel le code qui l' utilise fait référence . La fonction principale est d'augmenter la lisibilité du code et d'éviter toute ambiguïté. Par exemple, si le nom du champ de classe interne et l'argument de la méthode sont identiques :

public void setName(String name) {
   this.name = name;
}
Autrement dit, this.name est un champ du nom de l'objet et un argument de méthode. La référence this ne peut pas être utilisée dans les méthodes statiques. 2. ceci peut être utilisé dans un constructeur sous la forme d'un appel de méthode, comme this(value) . Dans ce cas, il s’agira d’un appel à un autre constructeur de la même classe. En bref, vous pouvez appeler deux constructeurs à la fois lors de la création d'un objet :

public Cat(int age, String name) {
   this(name);
   this.age = age;
}
 
public Cat(String name) {
   this.name = name;
}
Lorsqu'un objet Cat est créé et que le premier constructeur est appelé, les deux champs de l'objet seront appelés et initialisés avec succès. Il y a quelques nuances :
  1. this() ne fonctionne que dans le constructeur.
  2. Une référence à un autre constructeur doit figurer dans la première ligne du bloc constructeur (corps). Par conséquent, plus d’un (autre) constructeur d’une classe donnée ne peut pas être appelé dans un seul constructeur.
Analyse des questions et réponses des entretiens pour développeur Java.  Partie 4 - 5D'autres exemples se trouvent dans cet article .

35. Qu'est-ce qu'un initialiseur ?

Autant que je sache, dans cette question, nous parlons de blocs d'initialisation ordinaires et statistiques. Tout d’abord, rappelons ce qu’est l’initialisation. L'initialisation est la création, l'activation, la préparation au travail, la détermination des paramètres. Mettre un programme ou un composant dans un état prêt à être utilisé. Comme vous vous en souvenez, lors de la création d'un objet, une variable de classe peut être initialisée directement lors de sa déclaration :

class Cat {
   private int age = 9;
   private  String name = "Tom";
Ou définissez-le en externe via un constructeur :

class Cat {
   private int age;
   private  String name;
 
   public Cat(int age, String name) {
       this.age = age;
       this.name = name;
   }
Mais il existe un autre moyen : définir une variable d'objet interne via un bloc d'initialisation, qui ressemble à des accolades { } à l'intérieur de la classe, sans nom (comme une méthode ou un constructeur) :

class Cat {
   private int age;
   private  String name;
 
   {
       age = 10;
       name = "Tom";
   }
Autrement dit, un bloc d'initialisation est un morceau de code chargé lors de la création d'un objet. En règle générale, ces blocs sont utilisés pour effectuer certains calculs complexes nécessaires lors du chargement d'une classe. Les résultats de ces calculs peuvent être spécifiés sous forme de valeurs de variables. De plus, en plus des blocs d'initialisation classiques, il existe des blocs statiques, qui se ressemblent, mais qui ont le mot-clé static avant l'accolade :

class Cat {
   private static int age;
   private static String name;
 
   static{
       age = 10;
       name = "Tom";
   }
Ce bloc est exactement le même que le précédent. Mais si le standard est déclenché lorsque chaque objet est initialisé, alors le statique ne se déclenchera qu'une seule fois, lorsque la classe est chargée. En règle générale, dans un tel bloc, certains calculs complexes sont également effectués pour l'initialisation ultérieure des variables de classe statiques. Les mêmes restrictions s'appliquent à un bloc statique qu'aux méthodes statiques : il ne peut pas utiliser de données non statiques, ni une référence à l'objet actuel - this . Analyse des questions et réponses des entretiens pour développeur Java.  Partie 4 à 6Ensuite, nous pouvons voir l'ordre d'initialisation de la classe (avec son ancêtre) pour une meilleure compréhension du moment où les blocs d'initialisation sont déclenchés.

36. Pour hériter d'une classe public class Child extends Parent, écrivez l'ordre d'initialisation de l'objet

Lorsque la classe Child est chargée, l'ordre d'initialisation sera le suivant :
  1. Champs statiques de la classe Parent .
  2. Bloc d'initialisation statique pour la classe Parent .
  3. Champs statiques de la classe Сhild .
  4. Bloc d'initialisation statique pour la classe Child .
  5. Champs non statiques de la classe Parent .
  6. Il ne s'agit pas d'un bloc d'initialisation statique pour la classe Parent .
  7. Constructeur pour la classe Parent .
  8. Champs non statiques de la classe Child .
  9. Il ne s'agit pas d'un bloc d'initialisation statique pour la classe Child .
  10. Constructeur de la classe Child .
Analyse des questions et réponses des entretiens pour développeur Java.  Partie 4 à 7Voici un court article qui explique l'ordre d'initialisation en pratique.

37. Quelles relations connaissez-vous entre les classes (objets) ?

Il existe deux types de relations entre les classes en Java :
  • Relation IS-A
Le principe IS-A en POO est basé sur l'héritage de classe ou l'implémentation d'interface. Par exemple, si la classe Lion hérite de Cat , on dit que Lion est Cat :

Lion IS-A Cat
(mais tous les chats ne sont pas des Lions ) La situation est exactement la même avec les interfaces. Si la classe Lion implémente l' interface WildAnimal , alors ils sont également dans une relation :

Lion IS-A WildAnimal
  • Relations HAS-A
Ce type de relation repose sur l'utilisation de classes par d'autres classes, également appelée « association ». Une association est une classe faisant référence à une autre classe (ou même l'une à l'autre). Par exemple, la classe Car pourrait faire référence à la classe Passenger , et voici la relation :

Car HAS-A Passenger
Et vice versa : si Passenger a une référence à Car , alors ce sera la relation :

Passenger HAS-A Car

38. Quelles connexions associatives entre les objets connaissez-vous ?

L'agrégation et la composition ne sont que des cas particuliers d'association. L'agrégation est une relation dans laquelle un objet fait partie d'un autre. Par exemple, un passager peut être dans une voiture. Aussi, il peut y avoir plusieurs passagers ou pas du tout (si nous parlons d'une Tesla, alors le conducteur n'est pas obligatoire). Par exemple:

public class Car {
   private List passengers = new ArrayList<>();

 void setPassenger(Passenger passenger) {
     passengers.add(passenger);
 }

   void move() {
       for (Passenger passenger : passengers) {
           System.out.println("Перевозка пассажира - " + passenger.toString());
       }
       passengers.clear();
   }
}
Autrement dit, nous ne nous soucions pas du nombre de passagers (ou même s'il y en a) : la fonctionnalité de la classe Car n'en dépend pas. L'agrégation implique également que lorsqu'un objet est utilisé par un autre objet, le premier peut être utilisé dans d'autres objets. Par exemple, le même étudiant peut être membre à la fois d'un club de tricot et d'un groupe de musique de rockers, et en même temps rejoindre un groupe d'apprenants d'anglais. Comme vous le comprenez, l'agrégation est une relation associative plus lâche entre les classes. Analyse des questions et réponses des entretiens pour développeur Java.  Partie 4 à 8La composition est une relation encore plus rigide lorsqu’un objet fait non seulement partie d’un autre objet, mais que le travail de l’autre objet est très dépendant du premier. Par exemple, un moteur de voiture. Même si le moteur peut exister sans la voiture, il est inutile en dehors de celle-ci. Eh bien, une voiture ne peut pas fonctionner sans moteur :

public class Car {
   private Engine engine;
 
   public Car(Engine engine) {
       this.engine = engine;
   }
 
   void startMoving() {
       engine.start();
           ...
   }
La composition implique également que lorsqu'un objet est utilisé par un autre objet, le premier ne peut appartenir à quelqu'un d'autre. Si nous revenons à notre exemple, un moteur ne peut appartenir qu’à une seule voiture, mais pas à deux ou plusieurs à la fois. Nous nous arrêterons probablement ici aujourd'hui.Analyse des questions et réponses des entretiens pour développeur Java.  Partie 4 à 9
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION