Java: Constructeurs, gestion mémoire, et entrées/sorties

 

Constructeurs et héritage

Le code suivant illustre les mécanismes de construction d'instances :
 
class Machin {
    private int a = 2;
    public int b;
    public Machin(int b) {
this.b = b;
    }
    public Machin() {
this(12);
    }
    public String toString() {
return "[a="+a+"|b="+b+"]";
    }
}
 
class Truc extends Machin {
    public int c;
    public Truc() {
        // implicitement : super();
c = 3;
    }
    public Truc(int c) {
super(50);
this.c = c;
    }
    public String toString() {
return super.toString()+"+[c="+c+"]";
    }
    public static void main(String argv[]) {
Machin m = new Machin();    System.out.println(m); // [a=2|b=12]
m = new Machin(-3);         System.out.println(m); // [a=2|b=-3]
m = new Truc();             System.out.println(m); // [a=2|b=12]+[c=3]
m = new Truc(-1);           System.out.println(m); // [a=2|b=50]+[c=-1]
// Truc t = m;              // erreur compilation : "incompatible types"
Truc t = (Truc)m;           System.out.println(t); // [a=2|b=50]+[c=-1]
// System.out.println(m.c); // erreur compilation : "cannot find symbol"
System.out.println(t.c);    // -1
t = (Truc)new Machin();     // exception "java.lang.ClassCastException"
    }
}
 
Expliquez :
 
  • l'erreur de compilation "incompatible types"
  • l'erreur de compilation "cannot find symbol"
  • l'exception "java.lang.ClassCastException" 
 

Blocs d'initialisation satique et d'instances

Compilez et testez le code suivant :
 
class Instance {
    static int nbInstances;
    static int cptInstance;
    int numInstance;
    static {
nbInstances = 0;
    }
    {
nbInstances++;
cptInstance++;
numInstance = cptInstance;
    }
    public void finalize(){
nbInstances--;
    }
    public String toString() {
return "("+numInstance+")";
    }
 
    public static void main(String[] args) {
Instance i1 = new Instance();
Instance i2 = new Instance();
Instance i3 = new Instance();
System.out.println(i1+" "+i2+" "+i3+" total : "
  +nbInstances); // (1) (2) (3) total : 3
i2=i3;
System.gc();
System.out.println(i1+" "+i2+" "+i3+" total : "
  +nbInstances); // (1) (3) (3) total : 2
i1=null;
System.gc();
System.out.println(i1+" "+i2+" "+i3+" total : "
  +nbInstances); // null (3) (3) total : 1
    }
}
 
 
  • Expliquez les mécanismes d'instanciation
  • Cherchez dans l'API le rôle de System.gc()
  • Cherchez dans l'API le rôle de finalize() 
 

Compilez et testez le code suivant :

 
class Immortel {
    static int nbInstances;
    static int cptInstance;
    static Immortel zombie;
    int numInstance;
    static {
nbInstances = 0;
    }
    {
nbInstances++;
cptInstance++;
numInstance = cptInstance;
    }
    public void finalize(){
nbInstances--;
zombie=this;
    }
    public String toString() {
return "("+numInstance+")";
    }
 
    public static void main(String[] args) {
Immortel i1 = new Immortel();
Immortel i2 = new Immortel();
Immortel i3 = new Immortel();
System.out.println(i1+" "+i2+" "+i3+" total : "
  +nbInstances+" | "
  +zombie); // (1) (2) (3) total : 3 | null
i2=i3;
System.gc();
System.out.println(i1+" "+i2+" "+i3+" total : "
  +nbInstances+" | "
  +zombie); // (1) (3) (3) total : 2 | (2)
i1=null;
System.gc();
System.out.println(i1+" "+i2+" "+i3+" total : "
  +nbInstances+" | "
  +zombie); // null (3) (3) total : 1 | (1)
zombie = null;
System.gc();
System.out.println(i1+" "+i2+" "+i3+" total : "
  +nbInstances+" | "
  +zombie); // null (3) (3) total : 1 | null
    }
}
 
 
  • Expliquez la survie temporaire de i2 et de i1
  • Expliquez la mort du dernier zombie (voir API) 
 

Chargement de classes

Compilez et testez le code suivant :
 
class Chargement {
    static {
System.out.println("Chargement");
    }
    {
System.out.println("Instanciation (code commun)");
    }
    public Chargement() {
System.out.println("Instanciation (constructeur sans paramètre)");
    }
    public Chargement(int i) {
System.out.println("Instanciation (constructeur avec paramètre)");
    }
    public static void main(String[] args) throws Exception {
System.out.println("Main");
/*
 Chargement
 Main
*/
    }
}
 
class TestChargement1 {
    public static void main(String[] args) {
Chargement c;
System.out.println("-- Etape 1 --");
c = new Chargement();
System.out.println("-- Etape 2 --");
c = new Chargement(2);
/*
 -- Etape 1 --
 Chargement
 Instanciation (code commun)
 Instanciation (constructeur sans paramètre)
 -- Etape 2 --
 Instanciation (code commun)
 Instanciation (constructeur avec paramètre)
*/
    }
}
 
class TestChargement2 {
    public static void main(String[] args) throws Exception {
Chargement c;
System.out.println("-- Etape 1 --");
Class c_classe = Class.forName("Chargement");
System.out.println("-- Etape 2 --");
c = (Chargement)c_classe.newInstance();
System.out.println("-- Etape 3 --");
Class[] typeArg = {Integer.TYPE};
Object[] valArg = {new Integer(2)};
c = (Chargement)c_classe.getConstructor(typeArg).newInstance(valArg);
/*
 -- Etape 1 --
 Chargement
 -- Etape 2 --
 Instanciation (code commun)
 Instanciation (constructeur sans paramètre)
 -- Etape 3 --
 Instanciation (code commun)
 Instanciation (constructeur avec paramètre)
*/
    }
}
 
 
  • Expliquez les traces d'exécution des 3 méthodes main. Pour la dernière, référez-vous dans l'API aux classes Class et Constructor. 
 

Entrées/sorties

Completez la classe suivante :
 
import java.io.;
 
public class Util {
 
    public static String lireChaine(String prompt) {
BufferedReader entree = new BufferedReader(new InputStreamReader(System.in));
String s = null;
System.out.print(prompt);
try {
   s = entree.readLine();
} catch (IOException e) {
   System.out.println("Erreur d'entrée/sortie clavier");
}
return s;
    }
 
    public static int lireEntier(String prompt) {
        // retourne un entier lu au clavier
        // cf. classe Integer
        // Attention : gestion d'exception : voir le traitement de entree.readLine()
        //                                   dans la méthode lireChaine
    }
 
    public static boolean lireOuiNon(String prompt) {
        // retourne un booléen : true  si la chaîne saisie est "o" ou "O"
        //                       false si la chaîne saisie est "n" ou "N"
        // cf. classe String
    }
 
    public static void main(String argv[]) {
String ch = lireChaine("Chaîne : ");
int i = lireEntier("Entier : ");
boolean b = lireOuiNon("[o/n]  : ");
System.out.println(ch+" "+i+" "+b);
    }
}