IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Collection et Stream Java Discussion :

Instanciation d'un tableau d'éléments de type générique


Sujet :

Collection et Stream Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Inscrit en
    Novembre 2011
    Messages
    22
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2011
    Messages : 22
    Par défaut Instanciation d'un tableau d'éléments de type générique
    Bonjour,

    J'essaye d'instancier un tableau d'éléments de type générique T dans une constructeur d'une classe générique :

    Code java : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     
     
        class Plan<T> {
                public Plan(T[][] plan) {
                        this.plan = plan;
                }
     
                public Plan(int yTaille, int xTaille, int valeurParDefaut) {
                        plan = new T[yTaille][xTaille];
     
                }
     
                public T recevoirElement(int y, int x) {
                        return plan[y][x];
                }
     
                public int recevoirLargeur() {return xTaille;}
                public int recevoirHauteur() {return yTaille;}
     
                private T[][] plan;
                private int yTaille, xTaille;
        }

    L'erreur est ligne 9. Je sais pourquoi cela est interdit (limitation de la programmation générique en Java ; T est en fait remplacé par Object), mais j'aimerais bien contourner cette limitation. Je peux procéder ainsi :

    Code "java : Sélectionner tout - Visualiser dans une fenêtre à part
    plan = (T[][]) new Object[yTaille][xTaille];

    Mais ce n'est pas très propre et il reste un panneau attention à la compilation.

    Merci d'avance !

  2. #2
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    Et surtout ça ne marchera pas quand tu remontera un cran plus haut et que tu castera ton T[][] en, par exemple, Integer[][] car la jvm te lancera un ClassCastException (un Integer[][] n'est pas la même chose qu'un Object[][]).


    Le problème ici est le même que l'impossibilité de faire un new T(). La seule solution de contournement, c'est qu'on te passer une instance de T[][] et que, éventuellement, tu l'agrandisse. C'est ce que fait la classe ArrayList, dont je te suggère d'aller voir la méthode "T[] toArray(T[])" qui en dit long sur ce problème de generic et de tableau

  3. #3
    Membre averti
    Homme Profil pro
    Inscrit en
    Novembre 2011
    Messages
    22
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2011
    Messages : 22
    Par défaut
    Ah, mince, je souhaitais que ma classe se charge elle-même de tout construire... Mais n'a-t-on pas le même problème pour agrandir ?
    De ce que j'ai trouvé, la méthode n'en dit pas si long : http://docs.oracle.com/javase/7/docs...#toArray%28%29
    Et que la classe Integer aurait-elle de particulier pour ne pas pouvoir émaner d'un Object ?
    Dommage que la compatibilité ait voulue être conservée à tout prix avec des versions antérieures de Java lors de l'ajout de la programmation générique, ça bricke toutes les possibilités...

    (Merci pour ta réponse )

  4. #4
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    De la même manière que tu ne peux pas faire en java

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Object o = new Object();
    Integer i = (Integer) o;

    Tu ne peux pas faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Object[] o = new Object[1];
    Integer[] i  = (Integer[]) o;
    (Integer n'est qu'un exemple).

    Je parlais d'aller voir les sources, pas la javadoc

  5. #5
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 582
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 582
    Par défaut
    Oui enfin, ArrayList n'est pas magique. Elle fait bel et bien :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    T[] array = (T[])new Object[size];
    Le truc étant que le T[] array en question est private, n'est jamais exposé à l'extérieur, et n'est donc jamais casté après sa création. Ce qui évite le problème.

    Rien n'empêche de faire la même chose.
    Et pour le warning, ben il est normal : le compilateur signale qu'il n'est pas capable de vérifier la cohérence des types, et c'est la vérité. C'est le programmeur qui doit s'assurer qu'il ne fait pas de connerie, et notamment qu'il n'expose pas le tableau ainsi créé.
    Si on est sûr de soi, pour enlever le warning, il y a l'annotation "je sais ce que je fais, je comprends l'erreur et les risques qu'elle implique, mais la conception de cette classe garantit que ces risques ne s'appliquent pas" @SuppressWarnings("unchecked"). Une description de la preuve qu'il n'y a aucune risque, sera bienvenue dans les commentaires du code.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  6. #6
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    Citation Envoyé par thelvin Voir le message
    Le truc étant que le T[] array en question est private, n'est jamais exposé à l'extérieur, et n'est donc jamais casté après sa création. Ce qui évite le problème.
    C'est pour ça que je parlais de la méthode toArray qui retourn un T[], où là t'es bien obligé que le type sois correct, pas comme la variable privée qui elle absue du language dans tous les sens


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
         @SuppressWarnings("unchecked")
         public <T> T[] More ...toArray(T[] a) {
             if (a.length < size)
                 // Make a new array of a's runtime type, but my contents:
                 return (T[]) Arrays.copyOf(elementData, size, a.getClass());
             System.arraycopy(elementData, 0, a, 0, size);
             if (a.length > size)
                 a[size] = null;
             return a;
         }
    Tu notera que le seule moyen d'instancier un T[] correct, c'est d'avoir déjà un tableau, de faire un getClass() dessus et de passer par Arrays.copyOf dont l'implétentation utilise joyeusement le reflection

  7. #7
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Salut,

    Citation Envoyé par collect Voir le message
    Je sais pourquoi cela est interdit (limitation de la programmation générique en Java ; T est en fait remplacé par Object),
    Non au contraire c'est surtout une limitation des tableaux, qui ne garantissent pas un code typesafe (au contraire même).

    Avec des tableaux tu peux très bien écrire un code comme celui-ci sans avoir aucun problème à la compilation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    	T[] typedArray = ...
    	Object[] objectArray = typedArray; // OK
    	objectArray[0] = "Hello"; // ClassCastException
    Mais tu risques d'obtenir une exception à l'exécution selon le type réel de T...

    Tout cela à cause de l'héritage un peu trompeur des tableau (String[] hérite de Object[], etc.)
    D'ailleurs ceci est également vrai avant Java 5 et les Generics...



    Or l'objectif premier des Generics est d'empêcher les exceptions à l’exécution.
    Mais c'est impossible de faire cela avec des tableaux, donc la création de tableau Generics est bloqué pour éviter la confusion (croire que c'est typesage alors que cela ne l'est pas)






    Avec les Generics, tu n'a pas ce genre de problème, puis qu'il n'y a pas d'héritage des paramétrages.
    Tu auras forcément une erreur à la compilation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    	List<T> typedList = ...
    	List<Object> objectList = typedList; // COMPILE ERROR
    Au lieu de cela on peut utiliser la covariance/contravariance, mais ici aussi cela bloque les utilisations incorrects :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    	List<T> typedList = Arrays.asList(a);
    	List<?> objectList = typedList; // OK
    	objectList.add("Hello"); // COMPILE ERROR

    Bref :
    • tableau Java code non-typesafe
    • collections Generics code typesafe





    Citation Envoyé par collect Voir le message
    Mais ce n'est pas très propre et il reste un panneau attention à la compilation.
    Si tu veux vraiment utiliser un tableau tu devras faire avec ce warning, quitte à utiliser une annotation @SuppressWarning pour dire au compilateur que tu prends en charge la responsabilité du typeage de ce code.

    Par contre je te conseillerais plutôt de déclarer le tableau en Object, et d'utiliser deux méthodes get/set pour accéder à ses éléments, par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    class Plan<T> {
        public Plan(int yTaille, int xTaille) {
            plan = new Object[yTaille][xTaille];
        }
     
        @SuppressWarnings("unchecked")
    	public T get(int y, int x) {
                return (T)plan[y][x];
        }
     
        public void set(int y, int x, T value) {
        	plan[y][x] = value;
        }
     
        private Object[][] plan;
    }

    a++

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. tableau de structure(variable Type) traiter les éléments
    Par Patnel dans le forum Macros et VBA Excel
    Réponses: 1
    Dernier message: 18/04/2014, 08h48
  2. Réponses: 5
    Dernier message: 23/04/2013, 19h29
  3. Réponses: 37
    Dernier message: 18/05/2008, 23h20
  4. Tableau d'objets de type différents
    Par Hell dans le forum C++
    Réponses: 9
    Dernier message: 11/01/2005, 22h57
  5. Tableau d'éléments de type variable
    Par Drooxy dans le forum Langage
    Réponses: 4
    Dernier message: 16/03/2003, 15h20

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo