Questions d’entretien d’embauche Java Type System

Questions d'entretiens chez Java Type System

1. introduction

Java Type System est un sujet souvent abordé lors d'entretiens techniques pour les développeurs Java. Cet article passe en revue certaines questions importantes qui sont posées le plus souvent et peuvent être difficiles à résoudre.

2. Des questions

Q1. Décrivez la place de la classe d'objet dans la hiérarchie des types. Quels types héritent d’un objet et lesquels ne le font pas? Les tableaux héritent-ils d'un objet? Une expression Lambda peut-elle être affectée à une variable d'objet?

Lejava.lang.Object est au sommet de la hiérarchie des classes en Java. Toutes les classes en héritent, soit explicitement, implicitement (lorsque le mot-cléextends est omis de la définition de classe), soit transitivement via la chaîne d'héritage.

Cependant, il existe huit types primitifs qui n'héritent pas deObject, à savoirboolean,byte,short,char,int,float,long etdouble.

Selon les spécifications du langage Java, les tableaux sont également des objets. Elles peuvent être affectées à une référenceObject, et toutes les méthodesObject peuvent être appelées sur elles.

Les expressions Lambda ne peuvent pas être attribuées directement à une variableObject carObject n’est pas une interface fonctionnelle. Mais vous pouvez affecter un lambda à une variable d'interface fonctionnelle, puis l'affecter à une variableObject (ou simplement l'affecter à une variable Object en la convertissant en une interface fonctionnelle en même temps).

 

Q2. Expliquez la différence entre les types primitifs et de référence.

Les types de référence héritent de la classejava.lang.Object supérieure et sont eux-mêmes héritables (sauf les classesfinal). Les types primitifs n'héritent pas et ne peuvent pas être sous-classés.

Les valeurs d'argument primitivement typées sont toujours passées via la pile, ce qui signifie qu'elles sont passées par valeur et non par référence. Cela a les implications suivantes: les modifications apportées à une valeur d'argument primitif dans la méthode ne se propagent pas à la valeur d'argument réelle.

Les types primitifs sont généralement stockés à l'aide des types de valeur matérielle sous-jacents.

Par exemple, pour stocker une valeurint, une cellule mémoire de 32 bits peut être utilisée. Les types de référence introduisent l'en-tête d'en-tête d'objet présent dans chaque instance d'un type de référence.

La taille d'un en-tête d'objet peut être assez significative par rapport à une taille de valeur numérique simple. C'est pourquoi les types primitifs ont été introduits en premier lieu - pour économiser de l'espace sur la surcharge des objets. L'inconvénient est que tout en Java n'est pas techniquement un objet - les valeurs primitives n'héritent pas de la classeObject.

 

Q3. Décrivez les différents types primitifs et la quantité de mémoire qu'ils occupent.

Java a 8 types primitifs:

  • boolean - valeur logiquetrue /false. La taille du booléen n'est pas définie par la spécification JVM et peut varier selon les implémentations.

  • byte - valeur 8 bits signée,

  • short - valeur 16 bits signée,

  • char - valeur 16 bits non signée,

  • int - valeur 32 bits signée,

  • long - valeur 64 bits signée,

  • float - Valeur à virgule flottante simple précision 32 bits correspondant à la norme IEEE 754,

  • double - Valeur à virgule flottante double précision 64 bits correspondant à la norme IEEE 754.

 

Q4. Quelle est la différence entre une classe abstraite et une interface? Quels sont les cas d'utilisation de l'un et de l'autre?

Une classe abstraite est unclass avec le modificateurabstract dans sa définition. Il ne peut pas être instancié, mais il peut être sous-classé. L'interface est d'un type décrit avec le mot-cléinterface. Il ne peut pas non plus être instancié, mais il peut être implémenté.

La principale différence entre une classe abstraite et une interface réside dans le fait qu’une classe peut implémenter plusieurs interfaces, mais ne peut étendre qu’une seule classe abstraite.

Une classeabstract est généralement utilisée comme type de base dans une hiérarchie de classes, et elle signifie l'intention principale de toutes les classes qui en héritent.

Une classeabstract pourrait également implémenter certaines méthodes de base nécessaires dans toutes les sous-classes. Par exemple, la plupart des collections de cartes dans JDK héritent de la classeAbstractMap qui implémente de nombreuses méthodes utilisées par les sous-classes (comme la méthodeequals).

Une interface spécifie un contrat que la classe accepte. Une interface implémentée peut signifier non seulement l'intention principale de la classe, mais également des contrats supplémentaires.

Par exemple, si une classe implémente l'interfaceComparable, cela signifie que les instances de cette classe peuvent être comparées, quel que soit l'objectif principal de cette classe.

 

Q5. Quelles sont les restrictions sur les membres (champs et méthodes) d'un type d'interface?

Une interface peut déclarer des champs, mais ils sont implicitement déclarés commepublic,static etfinal, même si vous ne spécifiez pas ces modificateurs. Par conséquent, vous ne pouvez pas définir explicitement un champ d’interface commeprivate. En substance, une interface ne peut avoir que des champs constants, pas des champs d'instance.

Toutes les méthodes d'une interface sont également implicitementpublic. Ils peuvent également être soit (implicitement)abstract, soitdefault.

 

Q6. Quelle est la différence entre une classe interne et une classe imbriquée statique?

En termes simples, une classe imbriquée est fondamentalement une classe définie dans une autre classe.

Les classes imbriquées entrent dans deux catégories avec des propriétés très différentes. Une classe interne est une classe qui ne peut pas être instanciée sans instancier d'abord la classe englobante, c'est-à-dire toute instance d'une classe interne est liée implicitement à une instance de la classe englobante.

Voici un exemple de classe interne - vous pouvez voir qu'elle peut accéder à la référence à l'instance de classe externe sous la forme de la constructionOuterClass1.this:

public class OuterClass1 {

    public class InnerClass {

        public OuterClass1 getOuterInstance() {
            return OuterClass1.this;
        }

    }

}

Pour instancier une telle classe interne, vous devez avoir une instance d'une classe externe:

OuterClass1 outerClass1 = new OuterClass1();
OuterClass1.InnerClass innerClass = outerClass1.new InnerClass();

La classe imbriquée statique est assez différente. Syntaxiquement, c'est juste une classe imbriquée avec le modificateurstatic dans sa définition.

En pratique, cela signifie que cette classe peut être instanciée comme n'importe quelle autre classe, sans la lier à aucune instance de la classe englobante:

public class OuterClass2 {

    public static class StaticNestedClass {
    }

}

Pour instancier une telle classe, vous n'avez pas besoin d'une instance de classe externe:

OuterClass2.StaticNestedClass staticNestedClass = new OuterClass2.StaticNestedClass();

 

Q7. Java a-t-il plusieurs héritages?

Java ne prend pas en charge l'héritage multiple pour les classes, ce qui signifie qu'une classe ne peut hériter que d'une seule superclasse.

Mais vous pouvez implémenter plusieurs interfaces avec une seule classe, et certaines des méthodes de ces interfaces peuvent être définies commedefault et avoir une implémentation. Cela vous permet d’avoir un moyen plus sûr de mélanger différentes fonctionnalités dans une même classe.

 

Q8. Quelles sont les classes Wrapper? Qu'est-ce que la boxe automatique?

Pour chacun des huit types primitifs en Java, il existe une classe wrapper qui peut être utilisée pour envelopper une valeur primitive et l'utiliser comme un objet. Ces classes sont, en conséquence,Boolean,Byte,Short,Character,Integer,Float,Long etDouble. Ces wrappers peuvent être utiles, par exemple, lorsque vous devez placer une valeur primitive dans une collection générique, qui accepte uniquement les objets de référence.

List list = new ArrayList<>();
list.add(new Integer(5));

Pour éviter le problème de la conversion manuelle des primitives, une compilation automatique appelée autoboxing / auto unboxing est fournie par le compilateur Java.

List list = new ArrayList<>();
list.add(5);
int value = list.get(0);

 

Q9. Décrivez la différence entre égaux () et ==

L’opérateur == vous permet de comparer deux objets pour la «similitude» (c.-à-d. que les deux variables se rapportent au même objet en mémoire). Il est important de se rappeler que le mot-clénew crée toujours un nouvel objet qui ne passera l'égalité de== avec aucun autre objet, même s'ils semblent avoir la même valeur:

String string1 = new String("Hello");
String string2 = new String("Hello");

assertFalse(string1 == string2);

De plus, l'opérateur == permet de comparer des valeurs primitives:

int i1 = 5;
int i2 = 5;

assertTrue(i1 == i2);

La méthodeequals() est définie dans la classejava.lang.Object et est donc disponible pour tout type de référence. Par défaut, il vérifie simplement que l'objet est le même via l'opérateur ==. Mais il est généralement remplacé dans les sous-classes pour fournir la sémantique spécifique de la comparaison pour une classe.

Par exemple, pour la classeString, cette méthode vérifie si les chaînes contiennent les mêmes caractères:

String string1 = new String("Hello");
String string2 = new String("Hello");

assertTrue(string1.equals(string2));

 

Q10. Supposons que vous ayez une variable qui référence une instance d'un type de classe. Comment vérifier qu'un objet est une instance de cette classe?

Vous ne pouvez pas utiliser le mot cléinstanceof dans ce cas car il ne fonctionne que si vous fournissez le nom de classe réel comme littéral.

Heureusement, la classeClass a une méthodeisInstance qui permet de vérifier si un objet est une instance de cette classe:

Class integerClass = new Integer(5).getClass();
assertTrue(integerClass.isInstance(new Integer(4)));

 

Q11. Qu'est-ce qu'une classe anonyme? Décrivez son cas d'utilisation.

La classe anonyme est une classe one-shot qui est définie au même endroit où son instance est nécessaire. Cette classe est définie et instanciée au même endroit, elle n’a donc pas besoin d’un nom.

Avant Java 8, vous utilisiez souvent une classe anonyme pour définir l'implémentation d'une interface de méthode unique, commeRunnable. En Java 8, les lambdas sont utilisés à la place des interfaces de méthode abstraite simples. Mais les classes anonymes ont toujours des cas d'utilisation, par exemple, lorsque vous avez besoin d'une instance d'une interface avec plusieurs méthodes ou d'une instance d'une classe avec certaines fonctionnalités ajoutées.

Voici comment créer et remplir une carte:

Map ages = new HashMap(){{
    put("David", 30);
    put("John", 25);
    put("Mary", 29);
    put("Sophie", 22);
}};