Génériques Java


Les génériques Java (génériques) sont une nouvelle fonctionnalité introduite dans JDK 5. Les génériques fournissent un mécanisme de détection de sécurité de type au moment de la compilation, qui permet aux programmeurs de détecter les types illégaux au moment de la compilation.


L'essence des génériques est un type paramétré, ce qui signifie que le type de données sur lequel l'opération est effectuée est spécifié en tant que paramètre.

Supposons que nous ayons une telle exigence : écrire une méthode de tri capable de trier des tableaux d'entiers, des tableaux de chaînes ou même tout autre type de tableau. Comment l'implémenter ?

La réponse est d'utiliser Java Generics.

En utilisant le concept des génériques Java, nous pouvons écrire une méthode générique pour trier un tableau d'objets. Ensuite, appelez cette méthode générique pour trier un tableau d'entiers, des tableaux de flottants, des tableaux de chaînes, etc.


Méthode générique

Vous pouvez écrire une méthode générique qui peut recevoir différents types de paramètres lorsqu'elle est appelée. En fonction des types de paramètres transmis à la méthode générique, le compilateur gère chaque appel de méthode de manière appropriée.

Voici les règles de définition des méthodes génériques :

  • Toutes les déclarations de méthodes génériques ont une section de déclaration de paramètres de type (délimitée par des crochets angulaires) qui déclare la section des paramètres de type avant le type de retour de la méthode (<E> dans l'exemple ci-dessous).

  • Chaque partie de déclaration de paramètre de type contient un ou plusieurs paramètres de type, séparés par des virgules. Un paramètre générique, également appelé variable de type, est un identifiant qui spécifie le nom d'un type générique.

  • Les paramètres de type peuvent être utilisés pour déclarer des types de valeurs de retour et peuvent servir d'espaces réservés pour les types de paramètres réels obtenus par des méthodes génériques.

  • La déclaration d’un corps de méthode générique est la même que pour les autres méthodes. Notez que les paramètres de type ne peuvent représenter que des types de référence, pas des types primitifs (tels que int, double, char, etc.).

Exemple

L'exemple suivant montre comment utiliser des méthodes génériques pour imprimer des éléments de différentes chaînes :

public class GenericMethodTest
{
   // 泛型方法 printArray                         
   public static < E > void printArray( E[] inputArray )
   {
      // 输出数组元素            
         for ( E element : inputArray ){        
            System.out.printf( "%s ", element );
         }
         System.out.println();
    }

    public static void main( String args[] )
    {
        // 创建不同类型数组: Integer, Double 和 Character
        Integer[] intArray = { 1, 2, 3, 4, 5 };
        Double[] doubleArray = { 1.1, 2.2, 3.3, 4.4 };
        Character[] charArray = { 'H', 'E', 'L', 'L', 'O' };

        System.out.println( "整型数组元素为:" );
        printArray( intArray  ); // 传递一个整型数组

        System.out.println( "\n双精度型数组元素为:" );
        printArray( doubleArray ); // 传递一个双精度型数组

        System.out.println( "\n字符型数组元素为:" );
        printArray( charArray ); // 传递一个字符型数组
    } 
}

Compilez le code ci-dessus et les résultats en cours d'exécution sont les suivants Affiché comme :

整型数组元素为:
1 2 3 4 5 

双精度型数组元素为:
1.1 2.2 3.3 4.4 

字符型数组元素为:
H E L L O

Paramètres de type limités :

Il peut arriver que vous souhaitiez limiter la plage de types pouvant être transmis dans un paramètre de type. Par exemple, une méthode qui opère sur des nombres peut souhaiter accepter uniquement des instances de Number ou une sous-classe de Number. C'est le but des paramètres de type limité.

Pour déclarer un paramètre de type limité, indiquez d'abord le nom du paramètre de type, suivi du mot-clé extends, et enfin suivi de sa limite supérieure.

Exemple

L'exemple suivant montre comment « étend » est utilisé dans le sens général pour signifier « étend » (classe) ou « implémente » (interface). La méthode générique de cet exemple renvoie la valeur maximale de trois objets comparables.

public class MaximumTest
{
   // 比较三个值并返回最大值
   public static <T extends Comparable<T>> T maximum(T x, T y, T z)
   {                     
      T max = x; // 假设x是初始最大值
      if ( y.compareTo( max ) > 0 ){
         max = y; //y 更大
      }
      if ( z.compareTo( max ) > 0 ){
         max = z; // 现在 z 更大           
      }
      return max; // 返回最大对象
   }
   public static void main( String args[] )
   {
      System.out.printf( "%d, %d 和 %d 中最大的数为 %d\n\n",
                   3, 4, 5, maximum( 3, 4, 5 ) );
 
      System.out.printf( "%.1f, %.1f 和 %.1f 中最大的数为 %.1f\n\n",
                   6.6, 8.8, 7.7, maximum( 6.6, 8.8, 7.7 ) );
 
      System.out.printf( "%s, %s 和 %s 中最大的数为 %s\n","pear",
         "apple", "orange", maximum( "pear", "apple", "orange" ) );
   }
}

Compilez le code ci-dessus et le résultat en cours d'exécution est le suivant :

3, 4 和 5 中最大的数为 5

6.6, 8.8 和 7.7 中最大的数为 8.8

pear, apple 和 orange 中最大的数为 pear

Classe générique

La déclaration d'une classe générique est similaire à la déclaration d'une classe non générique, sauf qu'une partie de déclaration de paramètre de type est ajoutée après le nom de la classe.

Comme les méthodes génériques, la partie déclaration des paramètres de type d'une classe générique contient également un ou plusieurs paramètres de type, séparés par des virgules. Un paramètre générique, également appelé variable de type, est un identifiant qui spécifie le nom d'un type générique. Parce qu'elles acceptent un ou plusieurs paramètres, ces classes sont appelées classes paramétrées ou types paramétrés.

Exemple

L'exemple suivant montre comment nous définissons une classe générique :

public class Box<T> {
   
  private T t;

  public void add(T t) {
    this.t = t;
  }

  public T get() {
    return t;
  }

  public static void main(String[] args) {
    Box<Integer> integerBox = new Box<Integer>();
    Box<String> stringBox = new Box<String>();

    integerBox.add(new Integer(10));
    stringBox.add(new String("php中文网"));

    System.out.printf("整型值为 :%d\n\n", integerBox.get());
    System.out.printf("字符串为 :%s\n", stringBox.get());
  }
}

Compilez le code ci-dessus et le résultat d'exécution est le suivant :

整型值为 :10

字符串为 :php中文网