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 :

StringBuffer append Character = IOException ?? [FAQ]


Sujet :

Langage Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre Expert Avatar de KiLVaiDeN
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    2 868
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 2 868
    Par défaut StringBuffer append Character = IOException ??
    Bonjour,

    J'ai quelques points "sombres" :

    : J'essaie de faire un append sur mon StringBuffer. Lorsque je fais un append d'un objet String je n'ai aucun problème, mais lorsqu'il sagit d'un char il me demande d'intercepter une exception ( IOException ).. Je ne comprend pas pourquoi ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    StringBuffer mySB = new StringBuffer();
    mySB.append("c"); // ici aucun problème, pas d'exception à intercepter
    mySB.append('c');  // erreur il faut intercepter IOException !
    J'utilise WSAD 5.1.1, mon projet utilise la JRE de la SDK 1.5.0_03. J'ai regardé le code source de l'API, sans succès, je ne m'explique pas le pourquoi du comment.

    Suite à ça, et à mon exploration de code source, j'ai remarqué que l'API pouvait sûrement être optimisée par une idée toute simple que j'ai eu et que voici:

    Tout un tas de tests de validité de paramètres sont effectués en prenant l'exemple du append de StringBuffer.
    Voici un exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    public AbstractStringBuilder append(String str) {
    	if (str == null) str = "null"; // comparaison = cout CPU
            int len = str.length(); // affectation + appel de méthode = cout CPU
    	if (len == 0) return this; // comparaison = cout CPU
            // ici la suite de la méthode...
    Mais vous êtes d'accord avec moi, qu'il y a des cas où ces tests sont inutiles : par exemple si la chaine de charactère est une chaine constante et connue. Pourquoi l'API fait-elle quand même les tests dans ces cas là, et ne modifie pas le code "à la compilation" afin que la methode append soit changée en "appendSecure" par exemple, une version de append qui ne ferait pas ces tests de validité ?

    Juste une remarque Merci pour toute aide / suggestion,
    K

  2. #2
    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,


    Tu n'as normalement pas à intercepter d'IOException pour StringBuffer...
    Et c'est normal car tu n'écrit pas dans un fichier mais en mémoire...

    Toutefois depuis le JDK 1.5, StringBuffer implémente la nouvelle interface Appendable qui définit entre autre la méthode :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    public Appendable append(char c)
                      throws IOException
    Le problème peut venir de là... mais je trouve ca bizarre quand même...

    Je jetterais un oeil ce soir (ici je n'ai qu'une JDK 1.4.2)...

    a++

  3. #3
    Membre Expert Avatar de KiLVaiDeN
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    2 868
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 2 868
    Par défaut
    Bonjour et merci pour la réponse,

    Oui le problème doit venir de là, mais c'est quand même grave je trouve..
    Une idée par rapport à mon autre reflexion ?

    K

  4. #4
    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
    Citation Envoyé par KiLVaiDeN
    Oui le problème doit venir de là, mais c'est quand même grave je trouve..
    En regardant la javadoc je me suis apercu que les deux méthode append() de Appendable et StringBuffer ont un type de retour différent :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    // interface Appendable :
    Appendable append(char c) throws IOException;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    // class StringBuffer implements Appendable :
    StringBuffer append(char c);
    J'ai fait un test en java 1.4.2 et cela ne marche pas car StringBuffer ne respecte pas l'interface Appendable. Si on le droit d'enlever l'Exception, il n'est pas possible de modifier le type de retour...

    Mais il s'agit peut-être d'une nouveautée de Java 1.5.
    En effet si on regarde bien, la méthode append() de StringBuffer respecte celle de l'interface Appendable puisque StringBuffer implements Appendable...
    Je vais essayer de chercher plus d'info la dessus...

    Enfin tout ca pour dire que les EDI Java n'implémentent pas toutes les nouveautés de Java 1.5 et que le problème peut venir de là.
    (WSAD est basé sur eclipse et je ne pense pas que son support de Java 1.5 soit complet...)

    Donc essaye de compiler ce bout de code direct en ligne de commande avec javac. Si tu n'as pas d'erreur c'est que le problème vient de WSAD...

    Citation Envoyé par KiLVaiDeN
    Une idée par rapport à mon autre reflexion ?
    Je ne pense pas que ces tests soient couteux en CPU.
    Il s'agit de comparaison de référence et d'entier... C'est bien moins couteux qu'une gestion d'exception...
    Et en ce qui concerne l'appel de str.length(), il me semble que c'est optimizé par le compilateur...

    Bref je ne vois rien de bien méchant là dedans... au contraire...

    a++

  5. #5
    Membre Expert Avatar de KiLVaiDeN
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    2 868
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 2 868
    Par défaut
    J'ai trouvé un bout d'explication :

    An Appendable object is one that can have a character or CharSequence (or a sub-sequence of a CharSequence) appended to it. Implementations include StringBuffer and StringBuilder (if you don't already know about StringBuilder, do look it up), Writer (and subclasses), PrintStream, and java.nio.CharBuffer. Factoring the appendability out of these classes into the Appendable interface makes the new java.util.Formatter class more powerful: it can format text to any Appendable object, including your own implementations. (Exercise for the reader: can you make the TextFile class shown above both Iterable and Appendable?)
    Appendable doit donc gérer IOException, ce qui implique qu'on doit l'intercepter également pour StringBuffer, même si ce dernier ne déclenchera jamais ce type d'exception

    Merci pour les commentaires et explications et à bientot !

    K

  6. #6
    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
    Citation Envoyé par KiLVaiDeN
    Appendable doit donc gérer IOException, ce qui implique qu'on doit l'intercepter également pour StringBuffer, même si ce dernier ne déclenchera jamais ce type d'exception
    Mmm justement non...
    Si Appendable déclare une IOException c'est que dans certaines implémentations tu peux avoir une IOException (Writer, PrintStream,...).
    Mais StringBuffer 'supprime' cette exception car elle est inutile (StringBuffer utilise un tableau en mémoire, donc pas d' I/O).

    Si tu utilisais le code suivant je comprendrait l'utilité du try/catch car ton StringBuffer serait utilisé comme un Appendable :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    Appendable buffer = new StringBuffer();
    try {
       buffer.append ('c');
    } catch (IOException e) { /* ... */ }
    Mais dans ton cas je ne le comprend pas...
    Surtout que ca pose un problème de compatibilité avec les versions précédentes...

    PS : As-tu essayé de compiler avec javac ?

  7. #7
    Membre Expert Avatar de KiLVaiDeN
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    2 868
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 2 868
    Par défaut
    Citation Envoyé par adiGuba
    Mmm justement non...
    Si Appendable déclare une IOException c'est que dans certaines implémentations tu peux avoir une IOException (Writer, PrintStream,...).
    Mais StringBuffer 'supprime' cette exception car elle est inutile (StringBuffer utilise un tableau en mémoire, donc pas d' I/O).

    Si tu utilisais le code suivant je comprendrait l'utilité du try/catch car ton StringBuffer serait utilisé comme un Appendable :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    Appendable buffer = new StringBuffer();
    try {
       buffer.append ('c');
    } catch (IOException e) { /* ... */ }
    Mais dans ton cas je ne le comprend pas...
    Surtout que ca pose un problème de compatibilité avec les versions précédentes...

    PS : As-tu essayé de compiler avec javac ?
    Non je n'ai pas encore essayé..
    Mais il y a un fil que j'ai perdu : quand tu implémentes une interface, tu dois définir les méthodes de celles-ci y compris avec les exceptions qui vont bien non ?

    K

  8. #8
    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
    Citation Envoyé par KiLVaiDeN
    Mais il y a un fil que j'ai perdu : quand tu implémentes une interface, tu dois définir les méthodes de celles-ci y compris avec les exceptions qui vont bien non ?
    Non tu n'est pas obligé de lever les exceptions de l'interface...
    Ca ne change rien car tu respectes quand même la signature de l'interface.

    En effet, throws IOException signifie que la méthode peut dans certain cas renvoyer une IOException, mais ce n'est pas obligatoire...
    Et donc si la méthode que tu implémentes ne renvois pas d'exception, tu peux très bien l'enlever de la signature de ta surcharge...
    Le contrat est respecté...

    Tu peux même spécialiser l'exception par exemple en faisant un throws FileNotFoundException à la place (mais seulement parce que FileNotFoundException hérite de IOException...).
    Par contre tu ne peux pas déclarer une exception totalement différentes (ex. throws NullPointerException).


    Ce qui m'a géné en regardant la javadoc, c'est que StringBuffer 'change' le type de retour de la méthode append(char) déclaré dans Appendable. En effet jusqu'en java 1.4.2 ce n'étais pas possible...
    Mais je viens de trouver un article sur le sujet : COVARIANT RETURN TYPES.

    En gros cela dit que lorsqu'on implémente/redéfini une méthode, on peut spécialiser son type de retour (c'est à dire utiliser un type qui hérite du type de retour indiquer à l'origine).

    Donc je pense vraiment que le problème doit venir de WSAD qui a du mal avec cette nouvelle spécificitée de Java 1.5, et que si tu compiles avec javac l'erreur disparaitra...

    a++

    PS : Au passage c'est intérressant à savoir ça

  9. #9
    Membre Expert Avatar de KiLVaiDeN
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    2 868
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 2 868
    Par défaut
    Oui je comprend beaucoup mieux

    Merci pour les infos !

    K

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

Discussions similaires

  1. Réponses: 4
    Dernier message: 26/01/2010, 13h42
  2. StringBuffer (Problème avec .append())
    Par Ezarion dans le forum Langage
    Réponses: 7
    Dernier message: 19/01/2007, 17h06
  3. IB 6.0.1 - Win XP - Character Set
    Par SuperTotor dans le forum InterBase
    Réponses: 4
    Dernier message: 03/06/2003, 20h25
  4. [XMLRAD] invalid character type
    Par Sylvain James dans le forum XMLRAD
    Réponses: 4
    Dernier message: 10/12/2002, 07h47
  5. character set // Nls_lang
    Par fopicht dans le forum Oracle
    Réponses: 2
    Dernier message: 23/05/2002, 12h04

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