2015-11-30 39 views
5

Sto studiando Java efficace, articolo 8 (Rispettare il contratto generale quando si esegue l'override è uguale a). È stato spiegato abbastanza chiaramente dall'autore, ma alcune parti non sono ancora molto elaborate.Forma canonica di campo

Per questo esempio, si considera un CaseInsensitiveString classe definita come:

public final class CaseInsensitiveString { 
    private final String s; 

    public CaseInsensitiveString(String s) { 
     if (s == null) 
      throw new NullPointerException(); 
     this.s = s; 
    } 

    // Broken - violates symmetry! 
    @Override 
    public boolean equals(Object o) { 
     if (o instanceof CaseInsensitiveString) 
      return s.equalsIgnoreCase(((CaseInsensitiveString) o).s); 
     if (o instanceof String) // One-way interoperability! 
      return s.equalsIgnoreCase((String) o); 
     return false; 
    } 
    // ... // Remainder omitted 
} 

Alla fine di questo articolo, egli dice:

Per alcune classi, come CaseInsensitiveString di cui sopra, i confronti di campo sono più complessi dei semplici test di uguaglianza. Se questo è il caso, è possibile che lo memorizzi una forma canonica del campo, quindi il metodo equals può fare confronti esatti economici a confronto con queste forme canoniche piuttosto che comparare in modo più costoso e non esatto- isons. Questa tecnica è più appropriata per le classi immutabili (Articolo 15); se l'oggetto può cambiare, è necessario mantenere aggiornato il modulo canonico.

Ho cercato questo termine e ho scoperto che sostanzialmente si tratta di una rappresentazione standard di qualcosa, come il percorso assoluto senza collegamenti simbolici per un file in una directory. Ma non sono in grado di comprendere l'uso della forma "canonica" per questa classe, che sarebbe di aiuto in questo caso. Eventuali suggerimenti?

risposta

5

Penso che in questo particolare esempio, una forma canonica potrebbe memorizzare la versione in minuscolo o in maiuscolo della stringa e fare confronti su questo.

private final String s; 

public CaseInsensitiveString(String s) { 
    //for real code probably use locale version 
    this.s = s.toLowerCase(); 
} 

Questo rende il confronto di uguaglianza più conveniente perché siamo in grado di fare confronti tra stringhe esatte al posto del più costoso equalsIgnoreCase

// Broken - violates symmetry! 
@Override 
public boolean equals(Object o) { 
    if (o instanceof CaseInsensitiveString) 
     return s.equals(((CaseInsensitiveString) o).s); 
    if (o instanceof String) // One-way interoperability! 
     return s.equals((String) o); 
    return false; 
} 
+0

Grazie, abbastanza facile. Dovrebbe aver capito questo. Accettato! –