Escolar Documentos
Profissional Documentos
Cultura Documentos
Avoid finalizers
Finalizers are unpredictable, often dangerous, and generally unnecessary
try-catch block is used in Java to de-allocate resources - only if needed
can take a arbitrarily amount of time to execute the finalizer - dont do anything time-critical (e.g. closing file descriptors)
finalizer thread can have lower priority and may delay object destruction - JVM dependent
never depend on finalizers to store persistent states (they may not be executed at all)
no errors and no warnings thrown in finalizers -> corrupt state
severe penalty of performance
use it as a safety net and log a warning
FileInputStream, FileOutputStream, Connection, Timer - have this as a safety net
use to dispose of native peers (objects)
use a finalizer Guardian if your class is non-final and call the super.finalize() to make sure the subclass doesnt forget to call it
Obey the general contract when overriding equals(Object o) - use @Override annotation to avoid overloading the method instead (common mistake)
reflexive x.equals(s) = = true
transitive x.equals(y) => y.equals(z) => x.equals(z)
symmetric x.equals(y) => y.equals(x)
consistent multiple invocations of x.equals(y) should return the same result
for any non-null instance of x => x.equals(null) should return false
! there is no way to extend an instantiable class and add a value component to it and respect the equals contract
you can add a value comp. to a subclass of an abstract class without breaking the contract (Shape>Circle/Rectangle) as you cant instantiate the superclass
this is why you should favor composition over inheritance
to get this perfect:
use the == to check for the same reference
use instanceof to check if the argument is the correct type
cast the argument to the correct type (because instanceof precedes this, it will succeed)
for each significant field in the class, test if it matches the one in the other object
for primitives which are not float or double use == directly
for object reference fields invoke equals recursively
for float or double use Float.compare, respectively Double.compare
use (field == o.field || (field != null && field.equals(o.field))) (taking into account the possibility of the field containing null legitimately)
always override hashCode when overriding equals
Always override hashCode when overriding equals
use each significant field you used when overwrote equals
assuming that result is the value returned by your hash function:
start by storing some non-zero constant value (e.g. result = 17)
compute an int hashCode c for each significant field f
if field is boolean compute (f ? 1: 0)
if field is byte, char, short or int do (int) f
if field is long do (int)(f^(f>>>32))
if field is float do Float.computeToIntBits(f)
if field is double do Double.computeToLongBits(f) and do the long computation mentioned above
If the field is an object reference and this classs equals method compares the field by recursively invoking equals, recursively invoke hashCode
on the field. If a more complex comparison is required, compute a canonical representation for this field and invoke hashCode on the canonical
representation. If the value of the field is null, return 0 (or some other constant, but 0 is traditional)
If the field is an array, treat it as if each element were a separate field. That is, compute a hash code for each significant element by applying
these rules recursively, and combine these values per step 2.b. If every element in an array field is significant, you can use one of the
Arrays.hashCode methods added in release 1.5
Combine the hash code c computed in step 2.a into result as follows: result = 31 * result + c;
When you are finished writing the hashCode method, ask yourself whether equal instances have equal hash codes. Write unit tests to verify your
intuition! If equal instances have un-equal hash codes, figure out why and fix the problem