Dado el siguiente código de ejemplo, ¿hay alguna manera de inicializar el total modo que no tenga que hacer una verificación nula más tarde cuando lo use? No puedo pasar el valor al constructor.
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(); } }Me gustaría hacer algo como esto en el constructor:
this.total = new WeakReference<>(null);Pero eso no funciona. ¿Puedo inicializar una referencia débil en un estado liberado o eso va en contra del propósito de las clases?
Gracias
Editar
Gracias por todos los comentarios.
total.get() == null evaluando a falso después de inicializar con this.total = new WeakReference<>(null); Ahora entiendo que esa declaración es incorrecta. Esto se evaluará como verdadero. Sin embargo, creo que sería mejor no inicializarlo en nulo y simplemente verificar la condición nula antes del acceso.
Puedes inicializarlo así:
private WeakReference<Float> total = new WeakReference<>(null); Ahora la referencia en sí misma nunca será nula, pero su método get devuelve nulo.
Ejemplo del nuevo método de cálculo de porcentaje:
public float calculatePercentage(Float count) { Float totalF = total.get(); if(totalF == null) return -1; return count / totalF; } Sin embargo ,
en la mayoría de las situaciones tiene muy poco sentido usar WeakReference<Float> . ¿Por qué no usar simplemente el float primitivo? O si realmente quieres un objeto Float . Porque, ¿cuándo se recolectaría basura realmente el objeto Float? Creo que solo conduciría a un estado inconsistente y errores difíciles de rastrear.
Con el uso de WeakReference , siempre debe verificar la verificación nula antes de usar. Supongamos que hay un Objeto A cuya existencia depende de algún otro estado contextual.
Si dicho objeto se pasa a alguna clase que desconoce esos estados contextuales, siempre es mejor pasar el objeto envuelto en un objeto de WeakReference . A medida que el número de referencias fuertes a dicho objeto se convierte en 0, tras la ejecución del siguiente ciclo del recolector de basura, el objeto se recolecta como basura. En este punto, el objeto de WeakReference comenzará a dar un valor nulo cuando se invoque get() en él. Esta es una señal para la clase usuaria (que no conoce los estados contextuales) de que la vida útil del objeto ha terminado.
Antes de usarlo, la mejor manera es almacenar el objeto en una variable local (después de invocar get() ), verifique la verificación nula y luego úselo.
Aunque si ha verificado que no es nulo contra la condición de weakReference.get() no implica que no pueda ser nulo en la siguiente línea. Debe almacenar el objeto devuelto por get() en una variable local, verificar que no sea nulo y luego usarlo. Recuerde no almacenar el objeto (devuelto por get() ) como variable de instancia, ya que creará una referencia fuerte al objeto. Simplemente cree las variables locales y no pase estas variables locales a otros métodos. Solo úsalos allí y déjalos morir cuando termine su alcance.
Puede envolver y pasar el objeto usando un objeto de WeakReference ( new WeakReference< strongReferenceOfSomeObject >() ) como parámetro de método. Si lo pasa como parámetro de método o parámetro de constructor a la clase sin darse cuenta de los cambios de estado contextuales (que pueden decidir la vida útil del objeto), no debe asignarse a la variable de instancia. Si debe asignarse a una variable de instancia, solo debe almacenarse como WeakReference .
Consulte más en https://docs.oracle.com/javase/7/docs/api/java/lang/ref/WeakReference.html
PD Para Float , esto se puede resolver fácilmente usando float y no envolviendo Object of Float en una WeakReference . No necesita WeakReference para el código que ha incluido en cuestión. Mi respuesta anterior tiene como objetivo proporcionar una comprensión básica de alto nivel del uso de WeakReference en general.