Maison >Java >javaDidacticiel >Caractères génériques et paramètres de type limité en Java

Caractères génériques et paramètres de type limité en Java

php是最好的语言
php是最好的语言original
2018-08-06 16:55:421502parcourir

Caractère générique de type

Le caractère générique de type est généralement utilisé à la place des paramètres réels de type spécifiques (Voici les paramètres de type réels, pas les paramètres formels de type) . Lorsque vous n'avez pas besoin d'utiliser les fonctions spécifiques du type lors de l'exploitation d'un type, mais uniquement les fonctions de la classe Object, vous pouvez utiliser le caractère générique ? pour représenter les types inconnus. Par exemple, List6b3d0130bba23ae47fe2b8e8cddf0195 est logiquement la classe parent de tous les paramètres réels de type Listb8eff36bbb42b608e3cc5aaf9728ac04 tels que Listf7e83be87db5cd2d9a8a0b8117b38cd4, Listc0f559cc8d56b43654fcbe4aa9df7b4a, etc.

public class GenericTest {    
    public static void main(String[] args) {
        List<String> name = new ArrayList<String>();
        List<Integer> age = new ArrayList<Integer>();
        List<Number> number = new ArrayList<Number>();   
        name.add("zwj");
        age.add(18);
        number.add(120);
   
        getNumberData(age); // 报错
        getNumberData(number); // 120
        getData(name);  // zwj
        getData(age); // 18
        getData(number); // 120
        //getUperNumber(name); // 出现错误,方法中的参数已经限定了参数泛型上限为Number
        getUperNumber(age); //18
        getUperNumber(number); //120       
    }
    /**
     * 在使用List<Number>作为形参的方法中,不能使用List<Ingeter>的实例传入,
     * 也就是说不能把List<Integer>看作为List<Number>的子类;
     */
    public static void getNumberData(List<Number> data) {
        System.out.println("data :" + data.get(0));
    }
    /**
     * 使用类型通配符可以表示同时是List<Integer>和List<Number>的引用类型。
     * 类型通配符一般是使用?代替具体的类型实参,注意此处是类型实参;
     * 和Number、String、Integer一样都是一种实际的类型,可以把?看成所有类型的父类。
     */
    public static void getData(List<?> data) {
        System.out.println("data :" + data.get(0));
    }
    /**
     * 类型通配符上限通过形如List来定义,如此定义就是通配符泛型值接受Number及其下层子类类型。
     */
    public static void getUperNumber(List<? extends Number> data) {
          System.out.println("data :" + data.get(0));
    }
}

Paramètres de type limités

Parfois, nous souhaitons 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. À ce stade, Monkey doit ajouter une limite supérieure au générique, c'est-à-dire que l'argument de type transmis doit être un sous-type du type spécifié.

Pour déclarer un paramètre de type limité, indiquez d'abord le nom du paramètre de type, suivi du mot-clé extends ou super, et enfin suivi de sa limite supérieure ou inférieure. De là, nous pouvons savoir que l'ajout des limites supérieure et inférieure d'un générique doit être accompagné de la déclaration du générique.

d203bb1ae585225d4838a2b7e3d0503e indique que le type représenté par le caractère générique est une sous-classe du type T. Par exemple, lors de l'ajout d'éléments à une collection, vous pouvez ajouter soit un objet de type E, soit un objet de sous-type de E. Pourquoi? Parce que lors de la récupération, le type E peut recevoir à la fois des objets de classe E et des objets de sous-type E.

117c5a0bdb71ea9a9d0c2b99b03abe3e signifie que le type représenté par le caractère générique est la classe parent de type T. Par exemple, lors de l'obtention d'éléments d'une collection pour une opération, vous pouvez utiliser le type de l'élément actuel pour le recevoir, ou vous pouvez utiliser le type parent de l'élément actuel pour le recevoir.

public class GenericMethodTest {
    // 比较三个值并返回最大值
    public static <T extends Comparable<T>> T getMaxNuum(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.println( "结果 " + getMaxNuum(3, 4, 5) );  // 结果 5
        System.out.println( "结果 " + getMaxNuum(1.2, 6.6, 10.10) ); // 结果 10.10
   }
}

On peut également changer la définition précédente de la classe générique :

public class GenericClassDemo<T extends Number> { 
    private T t;   
    public GenericClassDemo() { 
    }
    public GenericClassDemo(T t) { 
        this.t = t;
    }
    public void setT(T t) {
        this.t = t;
    }
    public T getT(){ 
        return t;
    }
}

A ce moment, lors de l'instanciation de la classe générique GenericClassDemo, les types de paramètres ne peuvent être que Number et Number sous-catégorie. Sur cette base, regardons un exemple de méthode générique :

/**
 * 在泛型方法中添加上下边界限制的时候, 必须在泛型声明的时候添加;
 * 也就是在权限修饰符与返回值之间的<T>上添加上下边界
 */
public <T extends Number> T getT(GeneriClassDemo<T> demo){
    T t = demo.getT();
    return t;
}

Tableau générique

Vous ne pouvez pas créer un type générique exact en Java de tableau.

List<String>[] lsa = new ArrayList<String>[10];  // Not really allowed. 
Object o = lsa;    
Object[] oa = (Object[]) o;    
List<Integer> li = new ArrayList<Integer>();    
li.add(new Integer(3));    
oa[1] = li; // Unsound, but passes run time store check    
String s = lsa[1].get(0); // Run-time error: ClassCastException.

Dans ce cas, en raison du mécanisme d'effacement générique de la JVM, la JVM ne connaît pas les informations génériques au moment de l'exécution, vous pouvez donc attribuer une ArrayList à oa[1] sans qu'elle apparaisse, mais. lors de la récupération des données, une conversion de type est requise, donc une ClassCastException se produira. Si un tableau générique peut être déclaré, la situation ci-dessus ne provoquera aucun avertissement ou erreur lors de la compilation uniquement. L'erreur ne se produit qu'au moment de l'exécution. Lorsque vous restreignez la déclaration de tableaux génériques, dans de tels cas, vous pouvez être informé au moment de la compilation que le code présente des problèmes de sécurité de type, ce qui est bien mieux que pas d'invite du tout.

Les méthodes génériques suivantes sont autorisées : Le type du tableau ne peut pas être une variable de type, sauf si la méthode générique est utilisée, car pour la méthode générique, les données finales doivent être extraites Conversion de type explicite.

List<?>[] lsa = new List<?>[10]; // OK, array of unbounded wildcard type.    
Object o = lsa;    
Object[] oa = (Object[]) o;    
List<Integer> li = new ArrayList<Integer>();    
li.add(new Integer(3));    
oa[1] = li; // Correct.    
Integer i = (Integer) lsa[1].get(0); // OK

Articles connexes :

La différence entre T et le point d'interrogation (caractère générique) dans les génériques Java

Dans Java Explication détaillée des génériques

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn