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

Langage Java Discussion :

final + transient


Sujet :

Langage Java

  1. #1
    Membre expert
    Avatar de ®om
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    2 815
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 815
    Points : 3 080
    Points
    3 080
    Par défaut final + transient
    Si on a un attribut transient et final à la fois, quand on récupère l'objet sérialisé, on a l'attribut à null, et on peut pas le réinitialiser

    Y'a-t-il une solution?
    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
    17
    18
    19
    public class TestSerializable implements Serializable {
     
        private transient final List<String> s = new ArrayList<String>(); 
     
        public TestSerializable() {
            s.add("abc");
            s.add("def");
        }
     
        public static void main(String...args) throws Exception {
            TestSerializable ser = new TestSerializable();
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("test.dat")));
            oos.writeObject(ser);
            oos.close();
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("test.dat")));
            TestSerializable res = (TestSerializable)ois.readObject();
            System.out.println(res.s);
        }
    }
    Ceci affiche null...

  2. #2
    Expert confirmé
    Avatar de le y@m's
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2005
    Messages
    2 636
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Février 2005
    Messages : 2 636
    Points : 5 943
    Points
    5 943
    Par défaut
    Lors de la désérialisation, les phases d'initialisation ne sont pas effectuées et les attributs déclarés transient prennent leur valeur par défaut (par là je veux dire quand ils ne sont pas initialisés) ; par exemple un int vaudra 0, un boolean vaudra false et un Object (ce qui est ton cas) vaudra null.

    La seule solution à ton problème est d'implémenter la méthode readObject() afin d'initialiser ta List ; cependant pour cela ta List ne doit pas être final.
    Est-il vraiment nécessaire que tu la déclare final ? Etant donné quelle est private (et qu'elle ne risque donc pas d'être modifiée par une classe fille ou autre) je ne vois pas trop l'intérêt du final.

    Sans déclarer ta List final et en implémentant la méthode readObject() cela donnerait :
    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
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    public class TestSerializable implements Serializable {
     
        private transient List<String> s = new ArrayList<String>(); 
     
        public TestSerializable() {
            s.add("abc");
            s.add("def");
        }
     
        private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
            s = new ArrayList<String>();
            s.add("abc");
            s.add("def");
        }
     
        public static void main(String...args) throws Exception {
            TestSerializable ser = new TestSerializable();
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("test.dat")));
            try {
                oos.writeObject(ser);
            } finally {
                oos.close();
            }
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("test.dat")));
            TestSerializable res = null;
            try {
                res = (TestSerializable)ois.readObject();
            } finally {
                ois.close();
            }
            System.out.println(res.s);
        }
    }
    PS : pense à fermer tes fluxs dans un bloc try/finally
    Je ne répondrai à aucune question technique par MP.

    Pensez aux Tutoriels et aux FAQs avant de poster (pour le java il y a aussi JavaSearch), n'oubliez pas non plus la fonction Rechercher.
    Enfin, quand une solution a été trouvée à votre problème
    pensez au tag

    Cours Dvp : http://ydisanto.developpez.com
    Blog : http://yann-disanto.blogspot.com/
    Page perso : http://yann-disanto.fr

  3. #3
    Membre expert
    Avatar de ®om
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    2 815
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 815
    Points : 3 080
    Points
    3 080
    Par défaut
    Citation Envoyé par le y@m's
    Lors de la désérialisation, les phases d'initialisation ne sont pas effectuées et les attributs déclarés transient prennent leur valeur par défaut (par là je veux dire quand ils ne sont pas initialisés) ; par exemple un int vaudra 0, un boolean vaudra false et un Object (ce qui est ton cas) vaudra null.

    La seule solution à ton problème est d'implémenter la méthode readObject() afin d'initialiser ta List ; cependant pour cela ta List ne doit pas être final.
    Est-il vraiment nécessaire que tu la déclare final ? Etant donné quelle est private (et qu'elle ne risque donc pas d'être modifiée par une classe fille ou autre) je ne vois pas trop l'intérêt du final.

    Sans déclarer ta List final et en implémentant la méthode readObject() cela donnerait : ...

    PS : pense à fermer tes fluxs dans un bloc try/finally
    Oui, j'utilise readResolve(), ce qui revient au même...

    Le but de ma question était uniquement concernant les attributs "final"...
    Ca peut être utile pour "protected transient final" par exemple...

    Concernant la fermeture des flux, là c'est juste un test, donc pas de try


    Sinon un truc étrange, les chaînes "directes" sont conservées:
    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
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    public class TestSerializable implements Serializable {
     
        private transient final String s1 = "abc";
        private transient final String s2 = new String("def");
        private transient final List<String> list = new ArrayList<String>();
        private transient final int i = 5;
        private transient final Integer j = 6;
     
        public TestSerializable() {
            list.add("ghi");
        }
     
     
        public static void main(String...args) throws Exception {
            TestSerializable ser = new TestSerializable();
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("test.dat")));
            oos.writeObject(ser);
            oos.close();
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("test.dat")));
            TestSerializable res = (TestSerializable)ois.readObject();
            ois.close();
            System.out.println(res.s1);
            System.out.println(res.s2);
            System.out.println(res.list);
            System.out.println(res.i);
            System.out.println(res.j);
        }
    }
    affiche:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    abc
    null
    null
    5
    null

  4. #4
    Expert confirmé
    Avatar de le y@m's
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2005
    Messages
    2 636
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Février 2005
    Messages : 2 636
    Points : 5 943
    Points
    5 943
    Par défaut
    Après quelques tests, ya vraiment des trucs bizarres .
    Par exemple, si tes attributs s1 et i ne sont pas déclarés final, leur valeur n'est pas restaurée (cf mon message précédent), ils vaudront null et 0. Alors qu'en étant déclarés final ils les récupèrent (cf ton dernier exemple) cependant la List (list) et le String initialisé avec un new (s2) eux reste à null .
    J'avoue ne pas savoir pourquoi cette différence.
    Je ne répondrai à aucune question technique par MP.

    Pensez aux Tutoriels et aux FAQs avant de poster (pour le java il y a aussi JavaSearch), n'oubliez pas non plus la fonction Rechercher.
    Enfin, quand une solution a été trouvée à votre problème
    pensez au tag

    Cours Dvp : http://ydisanto.developpez.com
    Blog : http://yann-disanto.blogspot.com/
    Page perso : http://yann-disanto.fr

Discussions similaires

  1. Java EE 5 en version finale
    Par Petrus dans le forum Java EE
    Réponses: 12
    Dernier message: 13/05/2006, 16h01
  2. Problèmes avec les variables final
    Par casolaro dans le forum Langage
    Réponses: 7
    Dernier message: 09/12/2004, 14h29
  3. [Mots cles]Signification de transient et volatile
    Par Pill_S dans le forum Langage
    Réponses: 2
    Dernier message: 14/07/2004, 11h58
  4. [débutant]portabilité de l'exe final
    Par vvidal80 dans le forum MFC
    Réponses: 8
    Dernier message: 07/01/2004, 09h21

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