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

Java Discussion :

problème de Upcasting


Sujet :

Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Inscrit en
    Février 2013
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Février 2013
    Messages : 24
    Par défaut problème de Upcasting
    Voila, après avoir rencontré un problème sur l'upcast d'un objet java, j'ai fait une petite classe de test basique:

    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
    public class TestPoly {
    int a;
    int b;
    ....setter/getter}
     
    public class B extends TestPoly{
    	int a;
    	int b;
    ...constructeur/setter/getter }
     
    public class demo {
    	public static void main(String[] args) {
    		// classe mere
    		TestPoly m=new TestPoly();
    		//upcast ok fille-->mere
    		TestPoly b=new B();
    		// classe fille
    		B bb=new B();
    		// upcast : mere-->fille exdplicite (compile ok)
    		bb=(B)m;
    		// erreur 
    		//Exception in thread "main" java.lang.ClassCastException:TestPoly cannot be cast to B
    	}
    Pourquoi le second upcast explicite ne fonctionne pas a l’exécution?
    Je sais qu'il y a une liaison tardive a l’exécution et que le compilo accepte la possibilité que cela peut marcher.
    Mais pourquoi dans ce cas la, y a t il une ClassCastException ? Pourquoi le cast est impossible (surtout sur des classes aussi proches) ?
    Comment peut on prévenir cette exception ?

    thanks

  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,


    Le cast ne change pas le type réel de l'objet.
    Le compilateur laisse passer le cast car il peut être possible selon le cas.
    Mais à l'exécution tu as une instance de "TestPoly" et non pas de "B", et donc un ClassCastExwception.

    a++

  3. #3
    Membre averti
    Homme Profil pro
    Inscrit en
    Février 2013
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Février 2013
    Messages : 24
    Par défaut
    ok je comprends que le type de l'objet référencé est différent.
    Mais dis autrement pourquoi ne pas interdire cette pratique et faire une erreur tout de suite (via le compilo)..??
    ou dis autrement dans quelle cas de figure est-ce utile ?
    En plus, si je me souviens bien des principes du polymorphisme, il ne faut pas tenter de vérifier le type de l'objet par un Instanceof sinon ce n'est plus une bonne poo... non ?

  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
    Citation Envoyé par WebSteph0 Voir le message
    ok je comprends que le type de l'objet référencé est différent.
    Mais dis autrement pourquoi ne pas interdire cette pratique et faire une erreur tout de suite (via le compilo)..??
    Par ce que le compilateur n'en sais rien, dans la pluspart des cas. Tu lui dit, j'ai une variable, déclarée de type B et dans laquelle je met valeur qui est compatible avec B (donc B ou une de ses sous classe). Puis tu lui dit "maitenant, je veux pouvoir considérer que c'est un B2, sous classe de B". Ben pour le compilo, ça peux être le cas, il n'en sais rien, ça dépend de ce qu'il y aura réellement dans cette classe à l'exécution.


    Les cas où le compilateur réagit, c'est quand il est strictement impossible que ce soit le cas. Par exemple si tu as A qui n'est ni une sous classe ni une classe parente de B (donc qui n'a rien à voir), que tu prend une variable compatible A et que tu lui dit "maintenant c'est une B", là il va te lacher un truc genre "impossible qu'on est un B dans la variable de type A".


    Exemple:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Number x = createNumber();
    Integer y = (Integer)x; // C'est possible, mais pas certain
    ArrayList l = (ArrayList) x; // erreur: un Number ne pourra jamais être une ArrayList

  5. #5
    Membre averti
    Homme Profil pro
    Inscrit en
    Février 2013
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Février 2013
    Messages : 24
    Par défaut
    Merci pour ces reponses.
    Ok pour la possibilité de cast.
    Mais plus precisement, a l'execution, par quel mécanisme fait-il la différence entre un cast accepté ou refusé ? je vois mal encore la façon précise dont agit la jvm ...

  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
    Ben elle prend l'instance en question, elle regarde sa classe, et elle regarde si c'est compatible avec la cible. En "gros", elle fait

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    if (!B.class.isAssignableFrom(m.getClass()))
       throw new ClassCastException.

    Je dis "en gros" car au niveau bytecode, ça tiens en une instruction et ton code d'assignation ressemblera à un truc du genre

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    aload_1  // on lit la variable local numéro 1
    checkcast ton.package.B
    astore_2 // on stocke dans la variable locale numéro 2
    Tu notera, on m'arrêtera si je dis des bêtises, qu'au niveau assembleur, on peux violer gentillement le type des variable en stockant n'importe quoi dedans

  7. #7
    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
    Citation Envoyé par WebSteph0 Voir le message
    ou dis autrement dans quelle cas de figure est-ce utile ?
    Par exemple, chaque fois qu'on a affaire à un conteneur suffisamment versatile pour être utile à n'importe quel type d'objets, mais qu'aucun mécanisme de langage ne permet d'associer ce type lors de la compilation.

    Exemple : les Session J2EE. Peuvent contenir n'importe quelle donnée à garder pendant que la session de l'utilisateur est ouverte, et l'associer à un nom. À la compilation on ne sait donc pas le type précis de ces données, juste que chacune est d'un sous-type de Object.

    On pourrait toujours forcer la création de classes chargées de contenir ces données bien typées. Mais ça manquerait de flexibilité et compliquerait la vie plus que nécessaire. Si on va au bout des choses ça a aussi un coût en mémoire et en temps d'exécution.

    Citation Envoyé par WebSteph0 Voir le message
    En plus, si je me souviens bien des principes du polymorphisme, il ne faut pas tenter de vérifier le type de l'objet par un Instanceof sinon ce n'est plus une bonne poo... non ?
    C'est tout à fait exact. Il faut éviter de faire cela autant que possible. Et si on arrive à pas le faire du tout, on a une structure plutôt solide.

    Il n'empêche que ça reste de l'informatique, un outils industriel et pas la voix de Dieu, et que parfois, c'est trop dur ou les choses n'avaient pas été assez bien pensées depuis le début. Dans ce cas, plutôt que de juste se priver d'un mécanisme capable d'exister, on se contente de le décourager.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  8. #8
    Membre averti
    Homme Profil pro
    Inscrit en
    Février 2013
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Février 2013
    Messages : 24
    Par défaut
    Merci pour toutes ces réponses, qui couvrent la plupart des questions que je me posais sur ce problème d'Upcast.
    Je tout a fait d'accord avec thelvin, le mécanisme existe et on laisse le soin au développeur de gérer les cas limites. Mais on se retrouve quand même a mon sens avec un sérieux risque de vite dériver vers un code instable : un code qui compile avec pas mal de cas de plantage possible mais en contre partie une écriture plus facile. On arrive au limite du polymorphisme et aussi de la compréhension du mécanisme qu'il y a derrière...
    A moins qu'il n'existe un pattern de conception qui gère ce problème ?

  9. #9
    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
    "Ce problème" existe en milliers d'exemplaires tous très différents les uns des autres.
    Il y a des design patterns qui savent gérer certains d'entre eux, oui...
    Et il y en a d'autres où, à ma connaissance, l'usage du downcast est un moindre mal par rapport aux contraintes des autres méthodes. D'ailleurs il y a beaucoup de cas où le downcast ne rend rien instable en pratique, seulement il faut tester avant de livrer.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

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

Discussions similaires

  1. Problème d'installation oracle 8.1.7 sous NT
    Par Anonymous dans le forum Installation
    Réponses: 7
    Dernier message: 02/08/2002, 14h18
  2. Problème d'impression
    Par IngBen dans le forum C++Builder
    Réponses: 7
    Dernier message: 22/05/2002, 11h37
  3. Problème avec la mémoire virtuelle
    Par Anonymous dans le forum CORBA
    Réponses: 13
    Dernier message: 16/04/2002, 16h10
  4. Réponses: 6
    Dernier message: 25/03/2002, 21h11

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