Java


Rendu compte des questions rencontrées dans mon apprentissage

Je me sers de ce fichier comme

  1. la speech pour mes futurs entretiens
  2. le dépôt des doutes et leurs réponses que je recueilis

dans mon apprentissage. Je ne cherche pas une réponse détaillée (qu’on trouve facilement dans un livre ou un manuel).

Générale

  1. C’est quoi Java ?

    Java est un langage de programmation intermédiaire.

    • compilé : son compilateur produit un fichier qui n’est ni visible pour le développeur ni pour le système d’exploitation.
    • interprété : le fichier compilé
      • en bytecode Java avec l’extension CLASS, ou
      • en archive JAR doit être interprété par une machine virtuelle.
  2. Pourquoi utiliser Java ?

    • « Compiler une fois, exécuter partout. »
    • On y trouve beaucoup de libraries. Donc on a des algos testés, correctes et efficients qui accélèrent le développement sans réinventer la roule.
  3. C’est quoi une machine virtuelle ?

    C’est comme un tapis sur lequel on marche, et on regarde pas ce qui est au-dessous. Elle accepte un programme compilé par le compilateur Java sur n’importe quel système d’exploitation, puis elle l’exécute.

  4. En Java toutes les choses sont objets ?

    Non, c’est plutôt en JavaScript.

Variables, méthodes

  1. Affectation à une variable d’une valeur de type primitif vs celle d’un objet ?

    Considérons l’affection à une nouvelle variable de la valeur d’une variable existante.

    • en cas d’une variable de type primitif, le changement apporté à la valeur de la variable existante ne change pas celle de la nouvelle variable.

      char v1 = 'x';  // v2 = n/a, v1 = 'x'
      char v2 = v1;   // v2 = 'x', v1 = 'x'
      v1 = 'y';       // v2 = 'x', v1 = 'y'
      
    • en cas d’une variable de type objet, le changement apporté à la valeur de la variable existante change celle de la nouvelle variable.

      T o1 = new T();  // o2 =   n/a, o1 = <obj>
      T o2 = o1;       // o2 = <obj>, o1 = <obj>
      o1 = null;       // o2 =  null, o1 =  null
      
    • morale : faites attention quand vous passez un objet au paramètre d’une méthode, mais profitez-en.

  2. conversion parmi les String et d’autres types primitifs t ou la classe associée T :

    • String → ?
      • parser → t : T.parseT(str) (e.g. Integer.parseInt("123"))
      • méthode statique T.valueOf(str)T : e.g. Integer.valueOf("123")
      • char : "foo".charAt(1)
      • char[] : "foo".toCharArray()
      • String[] : "foo bar".split(regexStr)
    • ? → String
      • t : méthode statique String.valueOf(value)
      • T : toString()
      • T[] : méthode statique Arrays.toString(array)
    • casting : T v2 = (T) v1 pour v1 de type différent V.
      • Ça marche aussi pour t.
      • Une exception peut se produire. (e.g. v1 instanceof String et v2 instanceof int)
      • byte x = (byte) Math.E affecte 2 à x.
  3. const vs final

    • Le mot const n’est pas réservé en Java. On crée une constante en majuscule avec
      • le mot final devant son type
      • les mots dans son nom délimités par un tiret bas _
      • affection unique avec une valeur.
    • Le mot final est réservé et il signifie « l’affection une seule fois ». Une variable final n’est pas forcément constante à travers les exécutions.
    class C {
        final double c;
        C() { c = Math.random(); }
        public static void main(String[] args) {
            C c1 = new C(), c2 = new C();
            // sortie exemplaire : c1.c = 0.8759, c2.c = 0.6670
            System.out.println("c1.c = " + c1.c + ", c2.c = " + c2.c);
        }
    }
    
  4. Pourquoi passer par des méthodes ?

    Elles nous permettent de découper la problématique en morceaux plus facile à gérer.

  5. Méthode vs fonction

    Une fonction est une méthode. Elles partagent quelques points en commun :

    • Elles prennent en compte un n-uplet d’argument(s) si :
      • le nombre de membre(s) n dans l’uplet est égal au nombre de paramètre de la méthode.
      • pour i allant de 1 à n, le i-ième membre du n-uplet et le i-ième paramètre de la méthode sont de même type.
    • Elles englobent rien ou une suite finie d’instructions par une paire d’accolades {}.

    On reconnaît leur différence par leur type de retour :

    • comme en maths, une fonction retourne une valeur (probablement null, dépendant du contexte).
    • une méthode peut admettre void comme le type de retour.
  6. Quelle est la portée d’une variable ?

    • La portée d’une variable signfie l’ensemble des lignes où la variable est définie.
    • Cet ensemble commence par
      • variable locale : la ligne où elle est déclarée
      • variable globale : le début du bloc qui la contient
    • et il termine par la fin du bloc qui la contient.
  7. Comment remplir un tableau avec une valeur particulière ?

    Utiliser la méthode statique Arrays.fill(T[] array, T value).

  8. Dans le bloc de code suivant

    String[] words = new String[]{ "abc", "def", "ghi" };
    Integer[] gaps = new Integer[]{ 2, 1 };
    

    pourquoi on écrit Integer[] plutôt que int[] ?

    Pour être consistent.

Programmation orientée objets (POO)

  1. C’est quoi une classe et un objet ?

    • Une classe est comme un moule à partir duquel on fabrique un objet.
    • Une classe admet comme membres des attributs et des méthodes.
      • Un attribut détermine l’état d’un objet.
      • Une méthode caractérise le comportement d’un objet.
  2. C’est quoi l’héritage et le polymorphisme ?

    • L’héritage est un phénomène en lequel

      • une classe admet tous les attributs et toutes les méthodes d’une autre classe. Par exemple, un(e) délégué(e) est a priori un(e) étudiant(e). Donc, celui(celle)-là hérite tous les états et tous les comportements de celui(celle)-ci.

        • La classe de base peut être également appelée « class mère (ou bien superclasse) ».
        • La classe dérivée peut être également appelée « classe fille (ou bien sous-classe) ».
        • Remarque : le terme « classe héritée » est utilisé comme le synonyme de la « class fille », alors qu’une « classe hériante » est la classe mère.
      • une classe derivée fait le lien avec sa classe mère dans le code. En Java, la mention de la classe mère se fait par le mot clé extends.

        Remarque : on n’oublie pas ce point à cause de la possibilité de deux classes distinctes contenant les mêmes membres de classe sans le mot clé extends à droite du nom de classe.

        // A.java
        class A {
            int a = 0;
            int b(int c, int d) {return c + d;}
        }
        // B.java
        class B {
            int a = 0;
            int b(int c, int d) {return c + d;}
        }
        

        Les deux classes ci-dessus A et B vérifient le premier point, mais l’une n’est ni superclasse ni sous-classe de l’autre faut de mot clé extends.

    • Le polymorphisme est un phénomène en lequel deux classes distinctes sont dérivées d’une même classe. Reprenons l’exemple du(de la) délégué(e). Un(e) délégué(e) adjoint(e) est aussi dérivé(e) d’un(e) étudiant(e), mais son rôle est différent de celui d’un(e) délégué(e). Celui(celle)-ci et celui(celle)-là ont les méthodes suivantes en commun :

      • « apporter la feuiile d’appel »
      • « passer la feuiile d’appel »
      • « retourner la feuille d’appel signée ».

      Cependant, ils(elles) implémentent chaque méthode ci-dessus avec une différence : un(e) délégué(e) adjoint(e) regarde si un(e) délégué(e) est absent(e) avant d’exécuter la méthode.

  3. Qu’est-ce que le mot clé static signifie ?

    Il signifie « invocation depuis la classe ». Considérons une promotion d’étudiants comme une classe exemplaire.

    • un attribut (ou une propriété) statique exemplaire : le nombre d’étudaints (inscrits/présents/absents).
      • Il admet une seule valeur dans la classe.
      • L’extraction de sa valeur ne dépend d’aucune instance particulière de la classe.
      • Sa valeur peut être impactée par une méthode non statique. Par exemple, le départ d’un étudiant particulier décrémente le nombre d’étudiants présents par un.
    • une méthode statique exemplaire : une statistique de la classe, par exemple, l’âge moyen/médiane/mode/min/max de la classe.
      • Chaque statistique est une propriété de la classe, mais il est mieux de choisir une méthode plutôt qu’un attribut comme le type de membre de classe puisqu’elle est calculée par une suite d’instructions, ce qu’une méthode englobe.
      • Pour un exemple d’une méthode statique paramétrée, rappelons-nous le moment où notre prof nous demande un(des) volontaire(s) pour participer à son activité : on ajoute à la signature de la méthode un paramètre comme la taille de l’échantillon sampleSize, puis on tire aléatoirement un échantillon de taille précisée, d’où on calcule une valeur (ou bien un(e collection d’)objet(s)) à renvoyer.
  4. Que veut dire « encapsulation » ?

    • C’est de mettre des méthodes/attributs en private/package/proctected pour limiter l’accès des membres de classe extérieurs à cette méthode/cet attribut.
    • Les modificateurs d’accès précèdent le type de retour dans la déclaration d’un membre de classe.
    modificateur d’accès private package protected public
    traduction en français privé paquet protégé public
    par défaut
    même classe
    même paquet
    enfants
    autre situation
  5. Que signifie le mot this ?

    • l’objet actuel dans une méthode ou le constructeur de la classe contenante.

    • dans un constructeur qui admet un paramètre ayant le même nom avec un attribut de la classe contenante (e.g. attributName), this.attributName permet une distinction entre les deux.

    • surcharger le constructeur de la classe actuelle à la première ligne.

      class C {
          C() { System.out.println("Hello!"); }
          C(int x) { this(); System.out.println("x = " + x); }
          public static void main(String[] args) { C c = new C(0); }
      }
      
  6. interface vs classe abstraite ?

    • points en commun :
      • Elles peuvent contenir des méthodes abstraites publiques.
      • Elles peuvent contenir des attributs finaux statiques publiques.
    • différences :
      • Une interface n’admet que des méthodes abstraites publique.
  7. Quelle est une classe d’utilité ? Comment la créer ?

    Une classe qui

    • n’admet aucun enfant
    • n’admet aucune instance

    e.g. java.util.Math.

    public final C {
        private C() {
            throw new java.lang.UnsupportedOperationException("…");
        }
    }
    

Exceptions

  1. C’est quoi une exception ?

    Un état qui ne fait pas partie du processus normal, par exemple : saisir zéro comme le dénominateur pour la division.

    • exception checkée : vérifiée lors de la compilation
    • exception non checkée : pas vérifiée lors de la compilation
  2. Pourquoi et quand créer une exception étendant Exception ?

    Quand vous voulez un affichage personnalisé d’une erreur.

  3. Pourquoi on throws (lance) une Exception checkée à la signature ?

    • Le compilateur vérifie les exceptions checkées. Donc on montre à la signature que l’exception est gérée.

      class C {
          static void f() throws IllegalAccessException {
              System.out.println("Intérieur de fonction");
              throw new IllegalAccessException("démo");
          }
          public static void main(String[] args) {
              try {
                  f();
              } catch (IllegalAccessException e) {
                  System.out.println("Exception rattrapée.");
              }
          }
      }
      
    • throws une exception non checkée n’a pas de sens.

  4. Mélanger try-catch et if-else pour gérer/attraper une exception ?

    Mieux d’être consistent.

Saisie/sortie (I/O)

  1. C’est quoi un flux (*Stream) ?

    C’est comme un livre ouvert. Il ne permet qu’une seule personne de le regarder. Il peut modéliser une prise qui ne permet qu’un seul appareil d’y brancher.

  2. Comment utiliser la méthode mkdir()?

    1. Préciser le chemin (relatif à la racine du projet) File d = new File("foo/").
    2. Appeler cette méthode d.mkdir(). Cette méthode observe le modèle singleton.
  3. Comment lire un fichier ?

    • par FileReader et BufferedReader :

      // import java.io.File;
      // import java.io.IOException;
      // import java.io.FileReader;
      // import java.io.BufferedReader;
      
      File file = new File("foo/bar.txt");
      try {
          FileReader fr = new FileReader(file);
          BufferedReader br = new BufferedReader(fr);
          br.readLine();
          // read<Type>(); …
          br.close();
          fr.close();
      } catch (FileNotFoundException e) {
          // custom error
      } catch (IOException e) {
          // custom error
      }
      
    • par Scanner :

      // import java.io.File;
      // import java.io.IOException;
      // import java.util.Scanner;
      
      File file = new File("foo/bar.txt");
      try (Scanner sc = new Scanner(file)) {
          while (sc.hasNext()) {
              // next<Type>()
              String tempStr = sc.next();
          }
      } catch (FileNotFoundException e) {
          // custom error
      } catch (IOException e) {
          // custom error
      }
      

      Remarque : sc se ferme en tout cas dans le bloc ci-dessus.

Dates et fuseaux horaires

  1. Pourquoi ?

    Ces classes contiennent beaucoup de méthodes statiques pour le joli affichage.

Génériques

  1. Pourquoi utiliser les types génériques dans une méthode ?

    Pour éviter d’écrire le même code plusieurs mois pour de différentes classes.

  2. Il est possible de préciser un type borné par &, qui indique l’intersection des deux classes qui l’entourent. Il existe d’autres opérateurs binaires sur les deux classes comme la réunion, la différence, etc ?

    Non. Il faut mettre la classe de base (si elle existe) dans en premier, comme T extends C & I1 & I2. Sinon, il ne passe pas le compilateur.

Interface fonctionnelle et expressions lambda

  1. Est-ce qu’une interface fonctionnelle une instance de FunctionalInterface ?

    FunctionalInterface est une annotation d’interface que je ne maîtrise pas. Il est recommandé que toutes les interfaces fonctionnelles aient @FunctionalInterface pour + faciliter la lecture du code + permettre le lancement d’une erreur lors de la compilation en cas où l’interface annotée ne remplit pas les critères d’une @FunctionalInterface.

  2. Pourquoi créer une interface fonctionnelle ?

    Pour pouvoir utiliser les expressions lambda

    • sans préciser le nom et le type des arguments.
  3. Comment enchaîner deux expressions lambda représentant une fonction ?

    • Dans l’interface Function<T,R> dans le paquet java.util.function,
      • T et R sont respectivement les types de saisie et de retour de la fonction.
      • les méthodes f.andThen(g) et f.composite(g) modélisent respectivement g ∘ f et f ∘ g.
    • attention à la lisibilité du code lors de son comptage.

Classes anonymes

  1. C’est quoi ?

    Une classe qui n’a pas de nom implémentant une interface.

  2. Pourquoi ?

    L’implémentation unique avec le code concis.

  3. Exemple ?

    Une instance de launceur Netflix.

Java 

(Last modified on April 24, 2023)