2017-05-26 2 views
0

Un collègue et moi avons un désaccord sur un scénario particulier. Nous avons un objet Serializable qui a une méthode toString(). Ce toString() est implémenté en appelant le ReflectionToStringBuilder d'Apache. Quelque chose comme ceci:Appel de méthode statique dans un objet sérialisable

public class Foo implements Serializable { 
    // bunch of instance variables, getters and setters ... 

    @Override 
    public String toString() { 
     return ReflectionToStringBuilder.toString(this); 
    } 
} 

Nous n'avons aucun contrôle sur la façon dont ces objets sont transmis. Dans notre application particulière, nous pourrions les transmettre via des appels RMI, HTTP POST (après avoir écrit en tant que chaîne JSon), via JMS, ou via d'autres protocoles.

Maintenant, le cas de chaîne JSon ne devrait pas importer car il sera envoyé sous forme de chaîne afin que les détails d'implémentation de la méthode toString() n'a pas d'importance. Mais pour (certains des) autres protocoles, nous nous attendrions à sérialiser l'objet lui-même.

Une méthode d'une classe Serializable peut-elle appeler une méthode statique et être toujours (fonctionnellement) sérialisable? Il compile bien, bien sûr - mais peut-il encore être envoyé à travers le fil? Va-t-il échouer à désérialiser si le service de réception n'a pas la classe de la méthode statique sur son chemin de classe?

+3

Que diriez-vous de le tester? Qu'est-ce qui est sérialisé lors de l'envoi d'un objet sur le réseau, le code d'octet de la classe (que le récepteur a déjà dans son classpath), ou l'état de l'objet (que le récepteur ne connaît pas)? –

+1

Comment le service de réception peut-il avoir la classe mais pas la classe de la méthode statique? (demande en fait). Je pensais que quelle que soit la façon dont vous partagez la classe Serializable entre les services (qu'ils aient tous une bibliothèque ou que vous ayez dupliqué la classe dans chaque service), aucune bibliothèque externe ne doit-elle figurer dans le chemin de classe du code même compiler? – Ishnark

+0

Vous pouvez trouver une très bonne description à ce sujet [Règles de sérialisation statiques Java?] (Https: // stackoverflow.com/questions/6429462/java-static-serialization-rules) –

Répondre

1

Oui, cela fonctionnera. toString() n'est jamais appelé par le framework de sérialisation intégré de Java, il peut donc faire ce qu'il veut.

La plupart du temps, un objet sérialisé est simplement copié champ par champ, sans aucune méthode d'invocation de l'objet. Une classe peut modifier ce comportement par défaut en implémentant des méthodes spéciales (voir http://www.oracle.com/technetwork/articles/java/javaserial-1536170.html pour plus de détails), mais ce n'est pas le cas dans votre exemple. Ainsi, peu importe vos méthodes (pas seulement toString()), cela n'a pas d'importance pour la sérialisation.

Maintenant à la deuxième question: que se passe-t-il si ReflectionToStringBuilder n'est pas dans le classpath? C'est simple: rien ne se passe. Tant que ReflectionToStringBuilder n'est pas utilisé (c'est-à-dire que l'une de ses méthodes statiques est invoquée, ou que vous en créez une instance), cette classe n'est pas chargée (ou du moins pas liée), donc peu importe si elle est présente ou pas. Ce n'est que lorsque vous essayez d'utiliser réellement cette classe que vous obtiendrez un NoClassDefFoundError. La désérialisation de votre objet fonctionnera, mais si vous appelez toString(), vous obtenez une exception.

1

Votre exemple est totalement correct pour la sérialisation.

En théorie, la représentation JSON d'un objet Java est juste une autre forme de sérialisation. Toute la sérialisation le fait pour écrire l'objet "état" dans un flux et être capable de lire cet état à partir d'un flux. Il ne se soucie pas des opérations de l'objet ou de leur implémentation, y compris de la méthode toString. L'état de l'objet Java dans ce cas est représenté par ses variables d'instance et n'inclut pas les objets Définition de classe. Lorsque vous lisez votre Foo en arrière, vous devriez déjà avoir Foo.class avec ReflectionToStringBuilder.class d'Apache dans votre classpath.