2015-11-30 2 views
5

Я изучаю эффективную Java, пункт 8 (соблюдайте общий контракт при переопределении равных). Автор объяснил это довольно ясно, но все же некоторые детали не так уж много разработаны.Каноническая форма поля

В этом примере он рассматривает класс CaseInsensitiveString определяется как:

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 
} 

В конце статьи он говорит:

Для некоторых классов, таких как CaseInsensitiveString выше, полевых сравнений более сложны, чем простые тесты равенства. Если это так, вы можете захотеть, чтобы сохранил каноническую форму поля, поэтому метод equals может делать дешевые точные сравнения на этих канонических формах, а не более дорогостоящие неточные сопоставления - isons. Этот метод наиболее подходит для неизменяемых классов (пункт 15); если объект может измениться, вы должны сохранить каноническую форму в актуальном состоянии.

Я искал этот термин и обнаружил, что он в основном означает стандартное представление чего-то, например абсолютного пути, без каких-либо символических ссылок для файла в каталоге. Но я не могу понять использование «канонической» формы для этого класса, что поможет здесь. Какие-либо предложения?

ответ

5

Я думаю, что в этом конкретном примере каноническая форма может хранить строчную или прописную версию String и делать сравнения на этом.

private final String s; 

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

Это делает сравнение равенства дешевле, потому что мы можем сделать точные сравнения строк вместо более дорогого 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

Спасибо, довольно легко. Должно было понять это. Принято! –

Смежные вопросы