Types, classes et variables

Types et classes

Toutes les données manipulées dans un programme Java sont typées statiquement. Il en est ainsi des constantes, des variables et des expressions.
En particulier, la déclaration de toute variable suppose la spécification de son type que le compilateur utilisera pour vérifier la cohérence des différentes opérations la concernant et déterminer le type des expressions limpliquant. Toutes les vérifications et le typage des expressions sont réalisées par le compilateur et donc avant toute exécution : on parle de typage statique.

La notion de type présente en Java différents aspects ;


Un type référence est un type non primitif .

Les types références sont utilisés pour typer des expressions, et en particulier des variables de type référence) et permettent de désigner des objets (c'est-à-dire des instances de classes ou de tableaux). Ces types jouent un rôle analogue à celui des pointeurs, du langage C par exemple, en ce sens que les grandeurs de ces types sont des adresses en mémoire permettant d'accéder à ces grandeurs.

Les méthodes (c'est-à-dire les fonctions) sont par ailleurs elles-aussi typées et leur type prend en compte d'une part le type du résultat et le type des différents paramètres. Il peut s'avérer commode de considérer le type d'une méthode comme un type fonctionnel (au sens de langages comme CAML).

Ainsi, une fonction telles que

     T0 fonc(T1 v1, T2 v2, ..., Tn vn0 { ... }

a comme type

     T1 x T2 x ... x Tn → T0

Comme c'est le cas pour les variables, le typage des fonctions est statique. Comme nous le verrons, il s'agit là d'un point sensible en raison de la possibilité donnée par le langage

Le typage statique des fonctions signifie que le type de la méthode qui sera invoquée lors de l'exécution est déterminé dès la compilation. Cependant, le choix de la méthode qui sera effectivement invoquée à l'exécution n'est réalisé qu'à l'exécution.
Nous aurons bien évidemment l'occasion d'y revenir.


Les variables

On retrouve tout d'abord, comme dans tout langage de programmation, la notion d'identificateur qui est une suite de longueur quelconque de lettres et chiffres Unicode, le premier caractère étant une lettre.

On peut distinguer différentes catégories de variables selon le type qui leur est associé .


Les variables de type primitif

Ce qui caractérise une telle variable, c'est que sa déclaration entraîne implicitement l'allocation de l'espace mémoire nécessaire à mémoriser une grandeur du type associé.
Ainsi, la déclaration d'une variable entière int n; alloue les 32 bits utilisés pour coder les entiers suceptibles d'être affectés à la variable n. Dans certaines circonstances (variable d'instance), une valeur par défaut sera affectée à une telle variable lors de sa définition.

Les variables de type référence

Toute variable dont le type associé n'est pas un type primitif est qualifiée de type référence. Le rôle d'une telle variable sera de référencer/repérer/adresser une zone mémoire contenant un objet du type correspondant.

Concernant ces variables de référence, il ne faut pas perdre de vue que

leur déclaration ne donne lieu à aucune allocation en mémoire susceptible de contenir une grandeur du type référencé. Seul est alloué l'espace nécessaire à la mémorisation d'une adresse.

L'espace correspondant, fonction de la taille du type référencé, devra être alloué explicitement au travers de l'opérateur spécifique new qui réalise de fait la construction d'un objet du type donné (instanciation) et renvoie une adresse permettant de localiser et don accéder à l'objet créé.
Dans le cas de variables d'instance, les variables de type référence sont initialisées à la valeur null : toute tentative d'accès au travers d'une variable ayant cette «valeur» (accès à une variable d'instance ou invocation de méthode) provoque la levée de l'exception NullPointerException (un peu comme la tentative d'accès à la mémoire via un pointeur mal initialisé provoque l'envoi du signal SIGSEGV à un processus Unix et entraîne son interruption)


   --> cat Null.java
   class Null1 {
      int a;
      int getValeur(){return a;}
   }
   class Null2{
      Null1 nl;
   }
   public class Null{
      public static void main(String arg[]){
      Null2 obj = new Null2();
      System.out.println(obj.nl);
      System.out.println(obj.nl.getValeur());
      }
   }          
   --> java Null
   null
   Exception in thread "main" java.lang.NullPointerException    
   at Null.main(null.java:12)
   -->

ou un diagnostic du compilateur java s'il s'agit d'une variable locale non initialisée (c'est-à-dire même pas à la valeur null) comme ci-après :

   --> cat NonDefini.java
   class NonDefini1{
      int a;
      int getValeur(){return a;}
   }
   public class NonDefini{
      public static void main(String arg[]){
      NonDefini1 obj;
      System.out.println(obj.getValeur());
      }
   }   
   --> javac NonDefini.java
   NonDefini.java:8: variable obj might not have been initialized    
   System.out.println(obj.getValeur());
   
   1 error
   -->

Le cas particulier des tableaux

Parmi les variables de réference, il est courant de distinguer celles correspondant à des tableaux, du fait de la spécificité de leur déclaration.


Dans la séquence suivante

   Null1[ ] tabNull1;   
   tabNull1 = new Null1 [10] ;    

tabNull1 est déclarée comme une variable référençant un tableau d'objets de type Null1. La variable est , lors de sa définition, initialisée à null : aucune allocation n'est réalisée lors de la déclaration.
Là encore, l'allocation est réalisée au travers de l'opérateur new : chacun des 10 éléments du tableau est lui-même initialisé à la valeur null, car le type Null1 est un type référence (s'il s'agissait d'un tableau d'objets de type primitif la valeur serait 0).

Il est possible d'accéder à la taille d'un tableau au moyen de la variable length que tout tableau encapsule :


   --> cat Tableau.java
   class Tableau {
      static int[][] t = new int [3][4];
      public static void main(String [] arg){
         System.out.println(t.length);
         System.out.println(t[0].length);
         }
      }       
   --> java Tableau
   3  // un tableau [3][4] est un tableau de 3 tableaux de 4 éléments chacun   
   4  
   -->
   

Types primitifs et références

Il ressort de ce qui précède que les variables de types primitifs et les références ne sont pas traités de manière uniforme. Une variable de type primitif (et donc une valeur de ce type) est incompatible avec un type référence, ce qui en certaines circonstances constitue un handicap. Des passerelles sont fournies dans le package de base du langage sous la forme des classes constituant des enveloppes («wrappers») :

  • Integer
  • Long
  • Float
  • Double

Une expression de la forme  Integer(1000) renvoie une référence sur un objet encapsulant un entier de valeur 1000 dont la valeur peut être obtenue par invocation de la méthode int intValue() sur la référence de l'objet.



Dernière mise à jour : 16 juin 2005

Valid XHTML 1.0! Valid CSS!