6 votes

Initialise l'objet WeakReference pour éviter la vérification de nullité.

Étant donné l'exemple de code ci-dessous, existe-t-il un moyen d'initialiser total de sorte que je ne doive pas effectuer une vérification de la nullité plus tard lorsque je l'utilise. Je ne suis pas en mesure de passer la valeur dans le constructeur.

public class SampleCode 
{

    private WeakReference<Float> total;

    public SampleCode() {
    }

    public void setWidget(Float total) {
        this.total = new WeakReference<>(total);
    }

    public float calculatePercentage(Float count) {
        if (total == null) {
            return -1;
        }
        if (total.get() == null) {
            return -1;
        }

        return count / total.get();
    }
}

Je voudrais faire quelque chose comme ça dans le constructeur :

this.total = new WeakReference<>(null);

Mais cela ne fonctionne pas. Puis-je initialiser une WeakReference dans un état libéré ou cela va-t-il à l'encontre de l'objectif des classes ?

Gracias

Editar

Merci pour tous les commentaires.

  • L'utilisation de float était destinée à simplifier la question mais je peux tout à fait comprendre la confusion. L'objet réellement détenu par la référence faible est une vue dans un layout Android et cette classe vit en dehors du cycle de vie des activités.
  • total.get() doit être assigné à une valeur locale avant d'être évalué.
  • La déclaration "Cela ne fonctionne pas" était en relation avec :

total.get() == null évaluant à false après avoir initialisé avec this.total = new WeakReference<>(null); Je comprends maintenant que cette déclaration est incorrecte. L'évaluation sera vraie. Cependant, je pense qu'il serait préférable de ne pas l'initialiser à null et de vérifier la condition de nullité avant l'accès.

9voto

RobCo Points 2957

Vous pouvez l'initialiser comme ceci :

private WeakReference<Float> total = new WeakReference<>(null);

Maintenant la référence elle-même ne sera jamais nulle, mais c'est get renvoie effectivement la nullité.
Exemple de la nouvelle méthode calculatePercentage :

public float calculatePercentage(Float count) {
    Float totalF = total.get();
    if(totalF == null)
        return -1;

    return count / totalF;
}

Cependant ,
dans la plupart des situations, cela fait très peu de sens d'utiliser un WeakReference<Float> . Pourquoi ne pas simplement utiliser la primitive float ? Ou si vous voulez vraiment un Float objet. Parce que quand l'objet Float sera-t-il vraiment ramassé ? Je pense que cela ne ferait que conduire à un état incohérent et à des bogues difficiles à repérer.

6voto

nits.kk Points 3252

Grâce à l'utilisation de WeakReference vous devez toujours vérifier l'absence de contrôle de nullité avant de l'utiliser. Supposons qu'il existe un objet A dont l'existence dépend d'un autre état contextuel.

Si un tel objet est passé à une classe qui ne connaît pas ces états contextuels, il est toujours préférable de passer l'objet enveloppé dans un objet de type WeakReference . Lorsque le nombre de références fortes à cet objet devient nul, l'objet est mis au rebut lors de l'exécution du cycle suivant du collecteur d'ordures. À ce stade, l'objet de WeakReference commencera à donner un résultat nul lorsque get() est invoqué sur elle. C'est un signal à la classe utilisatrice (qui ne connaît pas les états contextuels) que la durée de vie de l'objet est terminée.

Avant de l'utiliser, le meilleur moyen est de stocker l'objet dans une variable locale (après avoir invoqué l'option get() ), vérifiez l'absence de contrôle et utilisez-le.

Même si vous avez vérifié l'absence de nullité par rapport à la condition de l'utilisateur. weakReference.get() n'implique pas qu'il ne peut pas être nul à la ligne suivante. Vous devez stocker l'objet retourné par get() dans une variable locale, vérifiez qu'elle n'est pas nulle et utilisez-la. N'oubliez pas de ne pas stocker l'objet (retourné par get() ) comme instance varaible car elle créera la référence forte à l'objet. Créez simplement les variables locales et ne passez pas ces variables locales à d'autres méthodes. Utilisez-les simplement à cet endroit et laissez-les mourir lorsque leur portée se termine.

Vous pouvez envelopper et passer l'objet en utilisant un objet de type WeakReference ( new WeakReference< strongReferenceOfSomeObject >() ) comme paramètre de la méthode. Si vous le passez en tant que paramètre de méthode ou de constructeur à la classe sans connaître les changements d'états contextuels (qui peuvent décider de la durée de vie de l'objet), il ne doit pas être assigné à une variable d'instance. S'il doit être assigné à une variable d'instance, il doit être stocké uniquement en tant que WeakReference seulement.

Pour en savoir plus, consultez le site https://docs.oracle.com/javase/7/docs/api/java/lang/ref/WeakReference.html

P.S. Pour Float ce problème peut être facilement résolu en utilisant float et ne pas envelopper les objets de Float dans un WeakReference . Vous n'avez pas besoin de WeakReference pour le code que vous avez inclus dans la question. Ma réponse ci-dessus a pour but de fournir une compréhension de base de haut niveau de ce qui suit WeakReference l'usage en général.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X