Forum Programmation.java Impossible d'affecter une adresse

Posté par  (site web personnel) .
Étiquettes : aucune
0
23
déc.
2004
Bonjour,

ce matin un problème très bête, dans notre beau langage préféré : le java.

Voici ma fonction, somme toute assez conne :

private void addObject(Object tab[],Object nb){

Object tmp[] = new Object[tab.length + 1];
int i = 0;
for (i=0;i<tab.length;i++){
// on recopie le tableau dans le nouveau tableau tmp
System.out.println("tmp["+ i+ "]=tab["+i+"];");
tmp[i]=tab[i];
}

tmp[i]=nb;
tab = tmp; // on retourne l'adresse du tableau tmp



}

J'etais persuadé que seuls les type primitifs etaient recopiés par valeur, mais visiblement dans mon code, le type Object aussi, et il me semble avoir eu des résultats similaire avec String : a la sortie de cette fonction, le tableau tab a toujours la meme adresse, il n'est jamais modifié, alors qu'il devrait normalement avoir l'adresse de tmp non ?

Merci pour votre aide.
  • # Ca me parrait normal ...

    Posté par  (site web personnel) . Évalué à 3.

    Tu fais une erreur, somme toute, assez fréquente.

    Le passage de paramètre en Java se fait TJS par valeur (même si on passe la valeur de la référence). Ca c'est correct.

    Ce que tu n'as pas compris c'est la notion de paramètre formel. Tes deux variables tab et nb sont créées en début de fonction (elles existent pour le bloc) ... et déctruitent à la fin du bloc. Si tu ajoutes un ... println avant ton accolade, tu verras que tab a bien l'adresse de tmp.

    Malheureusement, cette variable est détriute à la ligne suivante ... c'est dommage pour toi.

    Tu dois retourner cette valeur si tu veux que ça marche ...


    public static Object[] addObject ( Object[] tab ) {
    Object[] tmp = ...
    ...
    return tmp ;
    }


    NB : J'ai suprimé ta variable nb qui ne sert à rien.
    Rem : Ton code n'est pas très lisible (je sais c'est juste pour poser la question) ... tu devrais ajouter des blcs judicieusement placés, faire attention à tes noms de vars ... etc.
    • [^] # Re: Ca me parrait normal ...

      Posté par  . Évalué à 2.

      NB : J'ai suprimé ta variable nb qui ne sert à rien.
      
      
      D'après son code, si. Le but de sa fonction est de créer un tableau d'Object de taille [tab.length + 1], de copier le contenu du tableau tab ds tmp et d'ajouter nb dans la dernière case.
      
      
      Deux suggestions :
      
          // J'ai renommé nb en newVal
          private Object[] addObject(Object tab[], Object newVal) {
              Object result[] = new Object[tab.length + 1];
              // Utilisation de System.arraycopy() qui est bcp plus rapide que la boucle proposée - un peu comme memcpy en C
              System.arraycopy(tab, 0, result, 0, tab.length);
              reult[tab.length] = newVal;
              return result;
          }
      
      ou plus bêtement l'utilisation d'un Vector au lieu du tableau d'Object.
      • [^] # Re: Ca me parrait normal ...

        Posté par  (site web personnel) . Évalué à 1.

        En fait mon but est de faire un fonction générique. La voici dans son contexte :

        dans le code principal (alias est de type Integer[], code est de type String[]) :

        alias = (Integer [])addObject(alias,db.resultset.getInt("Alias"));
        code = (String[])addObject(code,db.resultset.getString("Code"));
        //Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object;


        dans la fonction on a donc comme vu précédemment :

        private Object [] addObject(Object [] tab,Object nb){

        Object tmp[] = new Object[tab.length +1];
        int i = 0;
        for (i=0;i<tab.length;i++){
        // on recopie le tableau dans le nouveau tableau tmp
        tmp[i]=tab[i];
        }
        return tmp; // on retourne l'adresse du tableau tmp

        }



        La solution simple serait de créér une fonction non-générique, mais n'y a t il pas moyen d'en faire une qui le soit ?
        • [^] # Re: Ca me parrait normal ...

          Posté par  . Évalué à 2.

          Le pourquoi de l'exception

          Dans la fonction, tu crées un tableau de type Object[] (qui peut contenir n'importe quel objet). Ce tableau est ensuite casté vers un tableau de type Integer[].
          Le cast ne marche que dans un sens !
          Dans le cas des objets, tu peux caster un Integer vers un Object (car Integer hérite de Object). Si tu essayes l'inverse, tu auras droit à un ClassCastException du plus bel effet. Pour les tableaux, c un peu pareil. Tu peux caster un tableau de type Integer[] vers Object[] (car Integer hérite de Object) mais l'inverse n'est pas possible (d'où le ClassCastException).

          Correctif - Utilisation de Vector

          Un Vector consiste en un tableau d'Object retaillable avec plein de fonctions autour (voir la doc).
          Tu replaces tes tableaux par des Vectors. Pour ajouter un objet à la fin du tableau, tu utilises la méthode put(Object valeur). Pour lire un objet à une position donnée tu utilises la méthode get(int index). Jusqu'à Java5, tu est obligé de caster le résultat du get pour obtenir le bon type. Depuis Java5 la généricité permet de s'affranchir dans pas mal de cas du cast.
          • [^] # Re: Ca me parrait normal ...

            Posté par  (site web personnel) . Évalué à 2.

            Oui ca marche merci beaucoup.
            En fait, maintenant comme je suis curieux, je voudrais savoir comment vector fonctionne, car mine de rien, il fait exactement ce que je voulais faire (stocker du int dans un tableau object, il en ajoute autant qu'on veut, puis après il les ressorts a la demande)

            Quelqu'un sait ?
            • [^] # RTFM

              Posté par  (site web personnel) . Évalué à 2.

              l'api java est très bien faite

              si si !
            • [^] # Re: Ca me parrait normal ...

              Posté par  . Évalué à 2.

              Si tu as le jdk, tu dois avoir un fichier src.zip contenant les sources Java de l'api (enfin, l'essentiel, tout ce qui est natif et certains fichiers sont absent).
              • [^] # Re: Ca me parrait normal ...

                Posté par  . Évalué à 1.

                Attention cependant si tu lis ce fichier, en effet ce source n'est pas libre, lis bien la licence du code avant.
                En particulier, si tu as lu ce code plus question de participer à un projet comme classpath.
          • [^] # Re: Ca me parrait normal ...

            Posté par  (site web personnel) . Évalué à 3.

            Depuis Java5 la généricité permet de s'affranchir dans pas mal de cas du cast.
            Ah que non non pas du tout, en Java5 le compilo met juste les casts à ta place, c'est du joli sucre syntaxique et les casts sont toujours nécessaire, les objets étant toujours stockés sous forme d'Object, ce qui a des graves conséquences en terme de performance lorsqu'on met un type primitif dans un truc générique.
            • [^] # Re: Ca me parrait normal ...

              Posté par  . Évalué à 2.

              Je parlais d'un point de vue code source. Bien sûr que le compilo va ajouter les casts de lui même mais c'est un point de vue bytecode/exécution.

              les objets étant toujours stockés sous forme d'Object, ce qui a des graves conséquences en terme de performance lorsqu'on met un type primitif dans un truc générique.
              Là, tu parles de l'autoboxing (la conversion automatique type-primitif <-> objet), ce qui sort du propos de mon post.

              Je persiste à dire que du point de vue du codeur Java (et du source qu'il va pondre), Java5 permet de s'affranchir du cast explicite (vu qu'il le fait implicitement) dans la plupart des cas (il y aura toujours des cas où le cast devra être explicite, genre un objet B héritant de A, un Vector et tu veux utiliser un méthode spécifique de B sur un objet contenu dans le vecteur).
              • [^] # Re: Ca me parrait normal ...

                Posté par  (site web personnel) . Évalué à 2.

                Effectivement les contre perfs sont dû à l'autoboxing, mais je voulais apporter des précisions, effectivement du point de vu du codeur celà ne change rien : il n'a pas besoin d'écrire les casts.
                Quoique s'il commence à faire mumuse avec l'introspection...
          • [^] # Re: Ca me parrait normal ...

            Posté par  . Évalué à 1.

            puisqu'on parle de perfs.... il vaut mieux utiliser ArraList plutot que Vector. ArrayList est bien plus rapide, mais pas synchronizée, ce qui peut etre un probleme dans un programme multi-thread

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.