2010-11-11 8 views
15

Qu'est-ce que JAXB a besoin d'un constructeur public sans-arg pour, lors du marshaling?Qu'est-ce que JAXB a besoin d'un constructeur public sans-arg?

Marshaller msh = ctx.createMarshaller(); 
msh.marshal(object, System.out); 

Je passe un objet, pas une classe. Pourquoi JAXB a-t-il besoin d'un constructeur? Pour construire quoi?

+0

Nitpick: Je suis sûr qu'il n'a pas besoin d'un constructeur * public * no-arg. Il a juste besoin d'un constructeur * any * no-arg. Il peut être protégé/privé/paquet-privé si vous le souhaitez. – MatrixFrog

Répondre

6

Une implémentation JAXB ne devrait pas avoir besoin d'un constructeur sans argument lors d'une opération marshal. JAXB en exige un pour unmarshalling. Normalement, l'absence d'un constructeur sans argument provoque une erreur lorsque le JAXBContext est créé. L'implémentation JAXB que vous utilisez peut retarder l'initialisation jusqu'à ce qu'une opération réelle soit effectuée.

En général, la prise en charge des constructeurs multi-arguments est quelque chose que nous devrions envisager dans une future version de JAXB. Dans le EclipseLink implementation of JAXB (MOXy), nous avons une demande d'amélioration ouverte pour cette fonctionnalité (ne hésitez pas à ajouter des détails pertinents):

Dans la version actuelle de JAXB vous pouvez utiliser une XMLAdapter pour soutenir ce cas d'utilisation:

+0

Avec 'XmlAdapter', je dois connaître la structure interne de la classe en cours de marshaling. Dans ce cas, pourquoi ne puis-je pas simplement ajouter un constructeur sans-argument? – yegor256

+2

@Vincenzo vous pourriez certainement ajouter simplement un constructeur no-arg. Si pour une raison quelconque vous ne pouviez pas modifier vos classes de modèle, un XmlAdapter pourrait être utilisé. –

4

La même chose que de nombreux cadres - la simplicité et la cohérence. Il permet à la bibliothèque d'appeler simplement Class.newInstance() sans avoir à se soucier de la façon de spécifier certaines dépendances pour un constructeur qui les prend. JAXB ne veut pas se préoccuper de l'injection de dépendances complète au-delà du paramétrage basé sur les attributs déjà effectué. C'est une honte à certains égards, car cela signifie que ces classes ne peuvent pas être immuables, mais c'est le compromis à faire.

+0

Tant que vous ne spécifiez pas quel paramètre est où dans le constructeur, je ne vois aucun moyen pour JAXB de le découvrir. La réflexion api ne donne que les types, pas de noms pour les arguments au constructeur. Comment devrait-il savoir que le premier paramètre (String) est le nom et pas un ID ou sthg comme ça? – ZeissS

+1

Correction à moi-même: l'annotation pourrait résoudre ce problème ... – ZeissS

+3

Je sais à quoi sert un constructeur public sans-arg, mais pourquoi JAXB en a-t-il besoin pendant le marshaling? Je passe une instance à 'marshal()', pas une classe. – yegor256

5

Comme d'autres l'ont noté, il ne devrait pas vraiment besoin d'un mais (au moins dans la mise en œuvre de Sun). Vous pouvez contourner cela avec un constructeur factice:

private MyObject() { 
    throw new UnsupportedOperationException("No-arg constructor is just to keep JAXB from complaining"); 
} 
+0

Vous ne pouvez pas jeter d'exception ici, JAXB utilise réellement ce c-tor – Derp

+0

Cela dépend si JAXB construit l'objet ou si ([comme les commentaires OP] (http://stackoverflow.com/questions/4155361/what- jaxb-needs-a-public-no-arg-constructor-for/12921496? noredirect = 1 # comment4484733_4155388)) vous le construisez vous-même et passez une instance à 'marshal()'. –