Divers Flashcards
Front, back ou fullstack ?
Profil fullstack mais forte volonté de me spécialiser côté back-end. C’est challengeant, on ne peut pas se reposer sur ses acquis, j’apprécie le fait de résoudre des problèmes parfois complexes.
Comment faites-vous votre veille ?
J’ai principalement un comple feedly qui agrège plusieurs sources de données afin de me tenir à jour. Je suis aussi des chaînes Youtube qui diffuse régulièrement des tutoriels, des astuces ou des conférences.
Static ?
Le mot-clé static est utilisable pour des variables, méthodes, classes internes ou blocs de code.
Le mot-clé static devant une variable (ou méthode) indique que celle-ci n’appartient pas à une instance particulière de la classe. Les variables ou méthodes statiques appartiennent à la classe elle-même. On peut ainsi les utiliser sans avoir une instance créée. De nombreuses classes ont des membres ou méthodes statiques.
La classe contient une ou des méthodes abstraites, qui n’ont pas de définition explicite. Une classe déclarée abstract ne peut pas être instanciée : il faut définir une classe qui hérite de cette classe et qui implémente les méthodes nécessaires pour ne plus être abstraite.
Différence entre set et List ?
List et Set sont des interfaces qui étendent l’interface Collection. Ici, nous allons discuter de la différence entre List, Set et Map en Java.
Définition de List
Une collection ordonnée (également appelée séquence). L’utilisateur de cette interface a un contrôle précis sur l’emplacement de chaque élément inséré dans la liste. L’utilisateur peut accéder aux éléments par leur index (position dans la liste) et peut rechercher des éléments dans la liste.
Définition de Set
Set est une collection qui ne contient aucun élément en double. Plus formellement, Set ne contiennent pas une paire d’éléments e1 et e2 tels que e1.equals(e2).
Définition de Map
Map est un objet qui mappe les clés aux valeurs. Une Map ne peut pas contenir des clés en double. chaque clé correspond à une valeur.
Qu’est-ce qu’une interface fonctionnelle ?
Pour simplifier, une interface fonctionnelle n’est rien d’autre qu’une interface avec une seule méthode abstraite. Et c’est ce qui permet d’implémenter facilement les expressions lambda. Avec cette annotation @FunctionalInterface, on indique au compilateur de bien vérifier que l’interface possède bien une seule méthode abstraite. C’est le même principe que l’annotation @Override.
Operation addition = (x,y) -> x+y
Qu’est-ce qu’un stream ?
Derrière ce nom se cache en fait un tout nouveau pattern de manipulation de données (remplaçant du pattern Iterator entre autre), qu’elles proviennent d’un tableau, d’une collection, d’un flux de fichier (avec java.nio par exemple), d’un flux réseau et j’en passe.
Avec les streams nous allons pouvoir parcourir, filtrer, manipuler, transformer nos données de façon séquentiel ou parallèles.
Les streams se trouvent dans le package java.util.stream et ils utilisent massivement les interfaces fonctionnelles pour appliquer des traitements.
Un stream ne stocke aucune donnée, il se contente de les transférer vers une suite instruction a opérer ;
Un stream ne modifie pas les données qu’il reçoit de sa source (flux, collection, tableau, …). S’il doit modifier des données, il doit au construire un nouveau stream.
Un stream est a usage unique : une fois utilisé complètement, impossible de l’utiliser une seconde fois. Si nous devons réutiliser les données d’une source une seconde fois, nous devrons recréer un second stream.
Un stream peut être infini si on ne clos pas le traitement dessus.
Les traitements fait sur un stream peuvent être de deux natures :
Intermédiaire : ce genre d’opération conserve le stream ouvert ce qui permet d’effectuer d’autre opérations dessus. Nous pourrons voir ceci lors de l’utilisation des méthodes map() ou filter() .
Terminale : c’est l’opération finale du stream, c’est ce qui lance la « consommation » du stream. La méthode reduce() en est un exemple.
Qu’est-ce qu’apporte les optionals ? Où et comment les utiliser ?
La classe Optional, apparue avec Java 8, sert de syntaxe alternative à une utilisation explicite du mot-clé null. Nous utilisons Optional pour vérifier la présence d’un élément facultatif (d’un élément qui peut ne pas exister) avant de l’utiliser.
N’utilisez pas optional sur votre retour de méthode si c’est un container (un tableau, une List ou Map), retournez un container vide.
N’utilisez pas optional pour vos attributs
N’utilisez pas optional pour vos paramètres de méthode
Quelles sont les prochaines nouveautés de Java ?
Inférence
Cette évolution s’inscrit dans la continuité de l’inférence de type des variables ajoutée avec Java 10. Il est désormais possible de ne pas spécifier explicitement le type des paramètres des lambdas en utilisant simplement le mot clé var.
Par exemple,
Function cube = (Integer x) -> x * x * x;
peut devenir :
Function cube = (var x) -> x * x * x;
Ceci peut représenter à la fois un gain de clarté, de concision et de temps lors de l’emploi de certains types à l’écriture assez lourde. Bien entendu, il n’était déjà pas obligatoire de spécifier un type pour les paramètres des lambdas, ainsi la déclaration :
Function cube = (x) -> x * x * x;
est tout à fait admissible.
A quoi sert donc l’inférence de type dans ce cas ? Elle est utile si l’on souhaite annoter nos paramètres, ce qui est impossible sans déclaration de type. En java 11, on pourra par exemple écrire des expressions telles que :
list.stream()
.map((@NotNull var s) -> s.toUpperCase());
java.lang.String : boolean isBlank(): retourne true si le String est vide ou n’est composé que de whitespaces, sinon false. Stream lines(): retourne un stream des lignes extraites du String. String repeat(int): retourne un String qui est le String d’origine concaténé avec lui-même n fois. String strip(): retourne un String débarrassé de ses trailing et leading whitespaces. Pour faire simple, strip() est la version «Unicode-aware » de trim() dont la définition du whitespace date des premières versions de Java. String stripLeading(): retourne un String débarrassé de ses leading whitespaces. String stripTrailing(): retourne un String débarrassé de ses trailing whitespaces
Avant Java 11, pour lancer le traditionnel HelloWorld.java, on exécutait :
javac -d HelloWorld.java
java -cp
Désormais, avec Java 11, on pourra directement lancer des applications contenues dans un seul fichier via :
java HelloWorld.java
Cette fonctionnalité, en complément de JShell, complète les outils à dispositions des développeurs débutants et permet également à Oracle de faire évoluer Java vers un langage plus léger à exécuter. Cela pourrait également illustrer sa volonté de faire entrer Java dans la cours des languages de scripting dans le futur. Affaire à suivre !
Qu’est-ce-qu’un objet immutable ? Pourquoi les privilégier ?
En Java nous avons la possibilité d’utiliser des objets immutables. Il s’agit d’objets, qui une fois initialisés, ne peuvent plus être modifiés. L’intérêt est notamment d’avoir des objets qui sont par définition thread safe, ce qui permet d’éviter d’avoir des blocs synchronized autour de ces objets.
Reflexivité
La réflexivité, aussi appelée introspection, consiste à découvrir de façon dynamique des informations relatives à une classe ou à un objet. C’est notamment utilisé au niveau de la machine virtuelle Java lors de l’exécution du programme. En gros, la machine virtuelle stocke les informations relatives à une classe dans un objet.
La réflexivité n’est que le moyen de connaître toutes les informations concernant une classe donnée. Vous pourrez même créer des instances de classe de façon dynamique grâce à cette notion.
Quel est le rôle original de Spring ?
SPRING est effectivement un conteneur dit « léger », c’est-à-dire une infrastructure similaire à un serveur d’application J2EE. Il prend donc en charge la création d’objets et la mise en relation d’objets par l’intermédiaire d’un fichier de configuration qui décrit les objets à fabriquer et les relations de dépendances entre ces objets.
Le gros avantage par rapport aux serveurs d’application est qu’avec SPRING, vos classes n’ont pas besoin d’implémenter une quelconque interface pour être prises en charge par le framework (au contraire des serveurs d’applications J2EE et des EJBs). C’est en ce sens que SPRING est qualifié de conteneur « léger ».
Outre cette espèce de super fabrique d’objets, SPRING propose tout un ensemble d’abstractions permettant de gérer entre autres :
Le mode transactionnel L'appel d'EJBs La création d'EJBs La persistance d'objets La création d'une interface Web L'appel et la création de WebServices Pour réaliser tout ceci, SPRING s'appui sur les principes du design pattern IoC et sur la programmation par aspects (AOP).
Final ?
La classe ne peut pas être modifiée, sa redéfinition grâce à l’héritage est interdite. Les classes déclarées final ne peuvent donc pas avoir de classes filles.
solid
Single responsibility principle (responsabilité unique) Le principe de responsabilité unique (Single responsibility) veut qu'une classe ne doit avoir qu'une seule responsabilité. Selon Robert C. Martin « A class should have only one reason to change ».
Open/closed principle (ouvert/fermé)
Liskov substitution principle (substitution de Liskov)
Interface segregation principle (ségrégation des interfaces)
Dependency inversion principle (inversion des dépendances)
Avec le principe d’inversion des dépendances (Dependency inversion principle), Robert C. Martin énonce que :
Les modules de haut niveau ne doivent pas dépendre des modules de plus bas niveau. Les deux doivent dépendre d’abstractions.
Les abstractions ne doivent pas dépendre des détails. Les détails doivent dépendre des abstractions.
solid
Single responsibility principle (responsabilité unique) Le principe de responsabilité unique (Single responsibility) veut qu'une classe ne doit avoir qu'une seule responsabilité. Selon Robert C. Martin « A class should have only one reason to change ». Comme son nom l’indique, ce principe signifie qu’une classe ne doit posséder qu’une et une seule responsabilité. Mais pourquoi me direz-vous ? Si une classe a plus d’une responsabilité, ces dernières se retrouveront liées. Les modifications apportées à une responsabilité impacteront l’autre, augmentant la rigidité et la fragilité du code.
Open/closed principle (ouvert/fermé)
Une classe, une méthode, un module doit pouvoir être étendu, supporter différentes implémentations (Open for extension) sans pour cela devoir être modifié (closed for modification).
public Car (EngineType engineType) {
engine = EngineFactory.getEngine(engineType) ;
}
@Inject
Engine engine
Liskov substitution principle (substitution de Liskov)
« Subtypes must be substituable for their base types. »
Les sous classes doivent pouvoir être substituées à leur classe de base sans altérer le comportement de ses utilisateurs. Dit autrement, un utilisateur de la classe de base doit pouvoir continuer de fonctionner correctement si une classe dérivée de la classe principale lui est fournie à la place.
Interface segregation principle (ségrégation des interfaces)
« Clients should not be forced to depend on methods that they do not use. »
Le but de ce principe est d’utiliser les interfaces pour définir des contrats, des ensembles de fonctionnalités répondant à un besoin fonctionnel, plutôt que de se contenter d’apporter de l’abstraction à nos classes. Il en découle une réduction du couplage, les clients dépendant uniquement des services qu’ils utilisent.
Dependency inversion principle (inversion des dépendances)
Avec le principe d’inversion des dépendances (Dependency inversion principle), Robert C. Martin énonce que :
Les modules de haut niveau ne doivent pas dépendre des modules de plus bas niveau. Les deux doivent dépendre d’abstractions.
Les abstractions ne doivent pas dépendre des détails. Les détails doivent dépendre des abstractions.
DI
L’injection de dépendances est un motif de conception qui propose un mécanisme pour fournir à un composant les dépendances dont il a besoin. C’est une forme particulière d’inversion de contrôle.
L’injection de dépendances permet à une application de déléguer la gestion du cycle de vie de ses dépendances et leurs injections à une autre entité. L’application ne crée pas directement les instances des objets dont elle a besoin : les dépendances d’un objet ne sont pas gérées par l’objet lui-même mais sont gérées et injectées par une entité externe à l’objet.