71. Que se passe-t-il si nous ne remplaçons pas la méthode toString() pour Enum ?
Disons que nous avons l' énumération suivante :public enum Role {
STUDENT,
TEACHER,
DIRECTOR,
SECURITY_GUARD;
}
Affichons l'élève dans la console en appelant toString() sur lui :
System.out.println(Role.STUDENT.toString());
Résultat dans la console :
72. Est-il possible de spécifier un constructeur à l'intérieur d'un Enum ?
Oui bien sûr. C'est via le constructeur que les valeurs des variables d'énumération internes sont définies. À titre d'exemple, ajoutons deux champs à l' énumération précédente - ageFrom et ageTo - pour indiquer la tranche d'âge pour chaque rôle :public enum Role {
STUDENT(5,18),
TEACHER(20,60),
DIRECTOR(40,70),
SECURITY_GUARD(18,50);
int ageFrom;
int ageTo;
Role(int ageFrom, int ageTo) {
this.ageFrom = ageFrom;
this.ageTo = ageTo;
}
}
73. Quelle est la différence entre == et equals() ?
C'est l'une des questions les plus courantes lors des entretiens avec les développeurs Java. Commençons par le fait que lorsque nous comparons des valeurs simples ( int , char , double ...), nous le faisons en utilisant == , puisque les variables contiennent des valeurs spécifiques et que nous pouvons les comparer. Et les variables primitives ne sont pas des objets à part entière - elles n'héritent pas de Object et n'ont pas de méthode equals() . Lorsque nous parlons de comparer des variables qui font référence à des objets, == comparera uniquement la valeur des références, qu'elles fassent référence au même objet ou non. Et même si un objet est identique à un autre, la comparaison via == donnera un résultat négatif ( false ), car il s'agit d'un objet différent. Comme vous le comprenez, la méthode equals() est utilisée pour comparer les variables de référence . Il s'agit de l'une des méthodes standard de la classe Object , nécessaire pour une comparaison complète des objets. Mais cela vaut la peine de préciser tout de suite : pour que cette méthode fonctionne correctement, elle doit être redéfinie en écrivant exactement comment les objets de cette classe doivent être comparés. Sauf si vous remplacez la méthode, elle comparera par défaut les objets par == . Dans IntelliJ IDEA , vous pouvez le remplacer automatiquement (à l'aide des outils IDEA) -> alt + insert , dans la fenêtre qui apparaît, sélectionnez equals() et hashCode() -> sélectionnez les champs de classe qui doivent participer -> et voilà, implémentation automatique de les méthodes sont terminées. Voici un exemple de ce à quoi ressemblerait une méthode égale générée automatiquement pour une simple classe Cat avec deux champs - int age et String name :@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || this.getClass() != o.getClass()) return false;
final Cat cat = (Cat) o;
return this.age == cat.age &&
Objects.equals(this.name, cat.name);
}
Si nous parlons de la différence entre == et égal pour les énumérations , il n'y en a pas beaucoup. Après tout, enum stocke des constantes, et même en comparant des valeurs similaires à l'aide de == , nous recevrons true , puisque les références concerneront toujours les mêmes objets. Eh bien, lors de l'utilisation d'equals, nous travaillerons également correctement sur la fonctionnalité, surtout si vous entrez dans le corps de la méthode equals pour une enum , vous verrez que dans la classe Enum , l'implémentation de la méthode est la suivante : Autrement dit, à l'intérieur - la bonne vieille comparaison par référence ! Pour résumer : pour enum , la comparaison à la fois via == et equals est correcte.
74. Que fait la méthode ordinal() dans Enum ?
Lors de l'appel de la méthode int ordinal() sur un élément enum , nous obtiendrons le numéro ordinal à partir de zéro de cette valeur dans la série générale d'énumérations. Utilisons cette méthode sur un élément de l' énumération précédente discutée - Role :System.out.println(Role.DIRECTOR.ordinal());
En conséquence, la console affichera :
75. Est-il possible d'utiliser Enum avec TreeSet ou TreeMap en Java ?
L'utilisation de types enum dans TreeSet et TreeMap est acceptable. Et on peut écrire :TreeSet<Role> treeSet = new TreeSet<>();
treeSet.add(Role.SECURITY_GUARD);
treeSet.add(Role.DIRECTOR);
treeSet.add(Role.TEACHER);
treeSet.add(Role.STUDENT);
treeSet.forEach(System.out::println);
Et la console affichera :
76. Comment les méthodes ordinal() et compareTo() sont-elles liées dans Enum ?
Comme indiqué précédemment, ordinal() renvoie le numéro ordinal d'une valeur dans une liste d'énumération générale. Aussi, dans l'analyse de la question précédente, vous avez vu que les éléments des énumérations, une fois par exemple dans un TreeSet (ensemble trié) prennent l'ordre dans lequel ils sont déclarés dans enum . Et comme nous le savons, TreeSet et TreeMap trient les éléments en appelant leur méthode compareTo() de l' interface Comparable . À partir de là, nous pouvons supposer que la classe Enum implémente l' interface Comparable , en l'implémentant dans la méthode compareTo() , dans laquelle ordinal() est utilisé pour définir l'ordre de tri. En entrant dans la classe Enum , nous en voyons la confirmation : Et le corps de la méthode elle-même : La méthode ordinal() n'est pas appelée ici. Au lieu de cela, la variable ordinale est utilisée - le numéro ordinal de l'élément dans l'énumération. La méthode ordinal() elle-même n'est rien de plus qu'un getter pour la variable ordinale .77. Écrivez un exemple EnumM
Dans les questions évoquées ci-dessus, j'ai déjà donné des exemples d'énumérations et je ne vois pas l'intérêt de dupliquer le code (par exemple, la question numéro 72 sur le constructeur dans l'énumération).78. Est-il possible d'utiliser Enum dans un boîtier de commutation ?
C'est possible et nécessaire ! En repensant à ma pratique, je remarque que l'un des endroits les plus courants pour utiliser enum est les constructions logiques comme switch . Dans ce cas, vous pouvez fournir toutes les variantes possibles de case , et après avoir écrit la logique pour toutes les valeurs d'énumération - et l'utilisation de l' opérateur par défaut n'est peut-être même pas nécessaire ! Après tout, si vous utilisez une chaîne ou une valeur numérique, par exemple de type int , vous pouvez recevoir une valeur inattendue, ce qui est impossible à utiliser avec une enum . À quoi ressemblerait un commutateur pour l’exemple évoqué précédemment :public void doSomething(Role role) {
switch (role) {
case STUDENT:
// некая логика для STUDENT
break;
case TEACHER:
// некая логика для TEACHER
break;
case DIRECTOR:
// некая логика для DIRECTOR
break;
case SECURITY_GUARD:
// некая логика для SECURITY_GUARD
break;
}
}
79. Comment obtenir toutes les valeurs disponibles dans une instance Enum ?
Si vous avez besoin d'obtenir toutes les instances d'une énumération, il existe une méthode values() qui renvoie un tableau de toutes les valeurs disponibles d'une énumération particulière dans l'ordre naturel (dans l'ordre dans lequel elles ont été spécifiées dans l' énumération ). Exemple:Role[] roles = Role.values();
for (Role role : roles) {
System.out.println(role);
}
La console affichera la sortie suivante :
API de flux
80.Qu’est-ce que Stream en Java ?
Java Stream est une façon relativement nouvelle d'interagir avec un flux de données, qui à son tour vous permet de traiter des données volumineuses de manière plus pratique et plus compacte, ainsi que de paralléliser le traitement des données entre un certain nombre de threads, ce qui peut améliorer les performances d'utilisation. Fonctionnalité. Ce sujet ne peut pas être abordé plus en profondeur, je vais donc laisser ici un lien vers un article qui peut vous aider à approfondir ce sujet.81. Quelles sont les principales propriétés des transactions ?
Le sujet s'appelle Stream API, mais la question concerne la transaction. Hmm... Tout d'abord, voyons ce qu'est une transaction. Une transaction est un groupe d'opérations de base de données séquentielles qui représentent une unité logique de travail avec des données. Une transaction peut être réalisée entièrement et avec succès, en préservant l'intégrité des données et indépendamment des autres transactions exécutées en parallèle, ou bien elle ne peut pas être réalisée du tout, auquel cas elle n'a aucun effet. Ainsi, les transactions ont quatre propriétés principales, appelées en abrégé ACID . Voyons comment chaque lettre de cette abréviation signifie : A - Atomicité - atomicité - cette propriété garantit qu'aucune transaction ne sera partiellement enregistrée dans le système. Soit toutes ses sous-opérations seront effectuées, soit aucune ne sera effectuée ( tout ou rien ). C - Cohérence - la cohérence est une propriété qui garantit que chaque transaction réussie n'enregistre que des résultats valides. Autrement dit, il s'agit d'une garantie qu'en cas de transaction réussie, toutes les règles et restrictions que le système impose sur des données spécifiques seront respectées, sinon la transaction ne sera pas terminée et les données du système reviendront à leur état précédent. État. I - Isolation - l'isolation est une propriété qui dit que lors de l'exécution d'une transaction, les transactions parallèles ne doivent pas affecter son résultat. Cette propriété est gourmande en ressources, elle est donc généralement mise en œuvre en partie en autorisant certains niveaux d’isolation qui résolvent certains problèmes d’isolation. Nous en discuterons plus en détail dans la question suivante. D - Durabilité - cette propriété garantit que si l'utilisateur a reçu la confirmation du système que la transaction a été effectuée, il peut être sûr que les modifications qu'il a apportées ne seront pas annulées en raison d'un échec. Autrement dit, vous pouvez être sûr qu'une sorte de panne du système d'exploitation n'aura aucun effet sur vos données si vous avez déjà reçu la confirmation de la réussite de votre transaction.82. Quels sont les niveaux d’isolement des transactions ?
Comme je l'ai dit plus tôt, fournir une isolation ACID est un processus gourmand en ressources. Cette propriété est donc partiellement satisfaite. Il existe différents niveaux d’isolement, et plus le niveau est élevé, plus l’impact sur la productivité est important. Avant de passer aux niveaux d'isolation des transactions, nous devons examiner les différents problèmes d'isolation insuffisante des transactions :-
lecture fantôme - lorsque le même échantillon (la même requête) est appelé à plusieurs reprises au sein de la même transaction, les données reçues diffèrent, ce qui se produit en raison des insertions de données par une autre transaction ;
-
lecture non répétitive - lorsque le même échantillon (la même requête) est appelé à plusieurs reprises au sein de la même transaction, les données reçues diffèrent, ce qui se produit en raison de modifications (mise à jour) et de suppressions de données par une autre transaction ;
-
lecture sale - le processus de lecture des données ajoutées ou modifiées par une transaction qui n'est ensuite pas confirmée (annulée), c'est-à-dire lire des données invalides ;
-
mise à jour perdue - lorsque différentes transactions modifient les mêmes données en même temps, toutes les modifications sauf la dernière sont perdues (ce qui rappelle le problème des « conditions de concurrence critique » dans un environnement multithread).
Niveau d'isolement | Lecture fantôme | Lecture non répétitive | Lecture sale | Mise à jour perdue |
---|---|---|---|---|
SÉRIALISABLE | + | + | + | + |
LECTURE RÉPÉTABLE | - | + | + | + |
LIRE ENGAGÉ | - | - | + | + |
LIRE NON ENGAGÉ | - | - | - | + |
AUCUN | - | - | - | - |
83. Quelle est la différence entre Statement et PreparedStatement ?
Et ici, la transition vers les fonctionnalités de la technologie JDBC n'est pas très fluide . Alors, commençons par comprendre ce qu'est réellement Statement . Il s'agit d'un objet utilisé pour générer des requêtes SQL. JDBC utilise trois types : Statement , PreparedStatement et CallableStatement . Nous n'examinerons pas CallableStatement aujourd'hui : parlons de la différence entre Statement et PreparedStatement .-
L'instruction est utilisée pour exécuter des requêtes SQL simples sans paramètres entrants insérés dynamiquement. PrepareStatement est utilisé avec la possibilité d'insérer dynamiquement des paramètres d'entrée.
-
Pour définir les paramètres dans PreparedStatement, les paramètres d'entrée dans la requête sont écrits sous forme de points d'interrogation, afin d'insérer ensuite une valeur à leur place à l'aide de divers setters, tels que setDouble() , setFloat() , setInt() , setTime() .. .. Par conséquent, vous n’insérerez pas le mauvais type de données dans votre requête.
-
PreparedStatement est « précompilé » et utilise la mise en cache, son exécution peut donc être légèrement plus rapide que l'interrogation à partir d'objets Statement . Par conséquent, les requêtes SQL exécutées fréquemment sont écrites sous forme d'objets PreparedStatement pour améliorer les performances .
-
L'instruction est vulnérable aux injections SQL, tandis que PreparedStatement les empêche. Apprenez-en davantage sur l'élimination des injections SQL et sur d'autres bonnes pratiques en matière de sécurité Java dans cet article .
GO TO FULL VERSION