/*
 * Un exemple de définition d'un type représentant les complexes.
 * Un complexe est un couple de réél (ici ils sont approximés par le
 * type double), avec une algèbre associée (on l'oublie ici).
 */
class Complexe {
  public double reelle;
  public double imaginaire;
}

/*
 * Un exemple de type dont les éléments "encapsulent" un entier (int)
 * Du point de vue Java, valeur est un attribut d'un élément du type.
 * On dit qu'un élément du type est une instance de la classe.
 * En Math on dit ensemble/élement
 * En POO/Java on dit classe/instance
 */
class Exemple {
  public int valeur;
}

public class Ex2 {

  /* Déclaration d'une variable statique, c'est-à-dire qui existe pour
   * toute la durée du programme. Elle apparaît avant l'appel au main (au
   * tout début de l'exécution), et elle
   * disparaît à la sortie du main (qu'à la toute fin de l'exécution).
   * On ne peut créer durant l'exécution de telles variables.
   * Leur nombre est déterminé à l'examen statique du code, lors de la
   * compilation. Elles sont stockées dans un espace particulier, l'espace des
   * variables statiques.
   * Suggestion wikipédia : entrées « Segment de données » et « Segment BSS ».
   * En pratique c'est un peu différent en Java, mais l'idée est là.
   */
  public static int N = 1234;

  /* Déclaration d'une fonction prenant en argument une valeur de type int.
   * À l'entrée de la fonction, on créé la variable i et on l'initialise
   * à la valeur passée au moment de l'appel. C'est l'appel par valeur ou
   * transmission par copie. On a donc ici une nouvelle variable i dont
   * la durée de vie est celle de l'appel. Lorsque l'appel termine la
   * variable disparaît.
   */
  public static void f(int i) {
    System.out.println(N);
    System.out.println(i);
    i = 10;
    System.out.println(i);    
  }

  /* Déclaration d'une fonction prenant en argument une valeur du type int[].
   * À l'entrée d'une telle fonction, on crée toutes les variables nécessaires
   * à sa bonne exécution. Donc, les paramètres (ici t) et les variables
   * locales (ici localI). Les variables paramètres sont initialisées avec les
   * valeurs transmises au moment de l'appel. C'est l'appel par valeur,
   * ou transmission par copie.
   * Même si ici t est une référence, il ne faut pas se laisser berner,
   * t est bien une nouvelle variable, le fait qu'elle désigne un objet
   * par ailleurs est une autre question.
   * Lorsque l'appel termine, on srot de la fonction en prenant soin de 
   * supprimer les variables créées en entrée.
   * Si on réfléchit à la création/disparition des variables locales
   * on s'aperçoit qu'une structure apparaît, les variables sont créées
   * au fur et à mesure que l'on effectue des appels, et disparaissent
   * lorsque l'appel se termine. Comme ces appels sont imbriquées les uns
   * dans les autres, la structure est celle d'une pile. On créé des
   * variables toujours à un bout et on supprime celles qui sont au bout.
   * Pensez à une pile d'assiettes...
   * Entrée wikipédia : pile (informatique).
   */
  public static void f(int []t) {
    System.out.println(N);
    int localI;
    System.out.println(t);
    System.out.println(t[2]);
    t[2] = 666;
    System.out.println(t[2]);    
  }

  /* main est une fonction qui n'a d'autre particularité que d'être la
   * première fonction appelée au démarrage de l'exécution. Elle fonctionne
   * comme toute autre fonction : elle reçoit des valeurs qui servent à
   * initialiser ses arguments qui sont des variables locales comme les
   * autres.
   */
  public static void main(String []args) {
    System.out.println(N);
    int a=3;
    int b=3;
    if (a==b) {
      System.out.println("egales");
    } else {
      System.out.println("non egales");
    }

    Exemple va=null;
    /* Attention, les variables créées par new sont particulières.
     * Leur durée de vie s'étend de leur création par new jusqu'à la
     * disparition de la dernière référence la désignant. Ces variables
     * sont des objets, et les objets ne sont, en Java, manipulables que
     * par l'intermédiaire de référénces.
     * La disparition d'une référence est elle liée à la terminaison de la
     * fonction ou elle est déclarée. La disparition d'une référence fait
     * que l'objet vers lequel elle pointe possède alors une référence de
     * moins. Lorsqu'un objet n'a plus de référence le désignant, il est
     * alors recyclable (il est placé dans la poubelle jaune).
     * Les objets ont une durée de vie de nature encore différente, ils
     * sont dans un espace particulier qui est le tas (heap).
     * Pointeur wikipédia : tas (allocation dynamique)
     */
    va = new Exemple();
    va.valeur = 3;

    /* Ici aussi il y a création d'un objet */
    Exemple vb = new Exemple();
    vb.valeur = 3;

    if (va==vb) {
      System.out.println("egales");
    } else {
      System.out.println("non egales");
    }

    vb = va;
    if (va==vb) {
      System.out.println("egales");
    } else {
      System.out.println("non egales");
    }

    System.out.println(a);
    f(a);
    System.out.println(a);

    int []t = new int[10];
    System.out.println(t[2]);
    System.out.println(t);
    t[2] = 999;
    System.out.println(t[2]);
    f(t);
    System.out.println(t[2]);
    int []t2 = new int[5];
    f(t2);
  }
}