Java: очевидный способ для автоматического броска UnsupportedOperationException при вызове хэш-кода () и равняется ()?

У нас есть кодовая база OO где в довольно большом количестве случаев hashcode() и equals() просто не работайте, главным образом по следующей причине:

Нет никакого способа расширить instantiable класс и добавить компонент значения, в то время как сохранение равняется контракту, если Вы не готовы воздержаться от преимуществ объектно-ориентированной абстракции.

Это - кавычка от "Эффективного Java" Joshua Bloch и существует больше на том предмете в большой статье Artima здесь:

http://www.artima.com/lejava/articles/equality.html

И мы совершенно здоровы, с которым, это не то, о чем этот вопрос.

Вопрос: замеченный, что это - то, что в некотором случае Вы не можете удовлетворить equals() контракт, каков был бы очевидный способ для автоматического создания hashcode() и equals() бросить UnsupportedOperationException?

Аннотация работала бы? Я думаю о чем-то как @NotNull: каждый @NotNull нарушение контракта действительно выдает исключение автоматически, и у Вас нет ничего иного, чтобы сделать помимо аннотирования Ваших параметров/возвращаемого значения с @NotNull.

Это удобно, потому что это - 8 символов (" @NotNull") вместо того, чтобы постоянно повторить тот же код исключения проверки/броска.

В случае, который я обеспокоен в каждой реализации где hashCode()/equals() не имеет никакого смысла, мы всегда повторяем то же самое:

@Override
public int hashCode() {
    throw new UnsupportedOperationException( "contract violation: calling hashCode() on such an object makes no sense" );
}

@Override
public boolean equals( Object o ) {
    throw new UnsupportedOperationException( "contract violation: calling equals() on such an object makes no sense" );
}

Однако это подвержено ошибкам: мы можем по ошибке забыть сокращать/вставлять это, и это может результаты в пользователях, неправильно использующих такие объекты (скажите путем попытки поместить их в наборы Java по умолчанию).

Или если бы аннотация не может быть сделана создать это поведение, AOP работал бы?

Интересно реальная проблема это самое присутствие hashCode() и equals() наверху иерархии Java, которая просто не имеет никакого смысла в некоторых случаях. Но тогда как мы имеем дело с этой проблемой чисто?

14
задан SyntaxT3rr0r 5 February 2010 в 07:26
поделиться

3 ответа

Почему бы вам не позволить вашей среде IDE (Eclipse / NetBeans / IntelliJ) сгенерировать hashCode () и равно ( ) методов для вас. Они неплохо справляются с этим.

АОП, конечно, будет работать, но это довольно сложная задача. А это будет означать, что вы не сможете использовать эти объекты практически без коллекции или утилит.

Другое логическое решение состоит в том, чтобы просто удалить реализации тех методов, где они не работают, таким образом, фактически оставив только реализации в Object .

4
ответ дан 1 December 2019 в 12:52
поделиться

Я согласен с вашей оценкой того, что это проблема с hashCode , а равно , определенным в Object в первую очередь. Я долгое время придерживался мнения, что с равенством следует обращаться так же, как и с порядком - с интерфейсом, говорящим «Меня можно сравнить с экземпляром X», а в другом - «Я могу сравнить два экземпляра X».

С другой стороны, действительно ли это вызывало у вас какие-либо ошибки? Пытались ли люди использовать равно и hashCode там, где им нельзя? Потому что даже если вы можете сделать так, чтобы каждый класс в вашей кодовой базы генерировал исключение, когда эти методы вызываются ненадлежащим образом, это не будет справедливо для других классов, которые вы используете, будь то из JDK или сторонних библиотек. .

Я уверен, что вы могли бы сделать это с помощью АОП в той или иной форме, будь то обычная обработка аннотаций или что-то еще - но есть ли у вас доказательства того, что вознаграждение того стоит?

Другой взгляд на это: это только в случае, когда вы расширяете другой класс, который уже переопределяет hashCode и равно , верно? В противном случае вы можете использовать характер метода hashCode / equals объекта «равенство = идентичность», который все еще может быть полезен.У вас очень много классов, которые попадают в эту категорию? Не могли бы вы просто написать модульный тест, чтобы найти все такие типы через отражение, и проверить, что эти типы вызывают исключение, когда вы вызываете hashCode / equals ? (Это может быть автоматизировано, если у них есть конструктор без параметров, или есть ручной список типов, которые были проверены - модульный тест может завершиться неудачно, если есть новый тип, которого нет в списке «заведомо исправных».)

10
ответ дан 1 December 2019 в 12:52
поделиться

Я не понимаю, почему вы думаете, что «в некоторых случаях вы не можете выполнить контракт equals ()»? Значение равенства определяется классом. Таким образом, использование Object равнозначно вполне допустимо. Если вы не переопределяете равных, вы определяете каждый экземпляр как уникальный.

Кажется, существует неправильное представление о том, что equals - один из тех методов, которые всегда нужно переопределять, и что он должен проверять все свои поля. Я бы поспорил с противоположным - не отвергайте равенство, если ваше определение равенства не отличается.

Я также не согласен со статьей artima, в частности, «Ловушка № 3: определение равных в терминах изменяемых полей». Для класса вполне допустимо определять свое равенство на основе изменяемых полей.Пользователь должен знать об этом при использовании его с коллекциями. Если изменяемый объект определяет свое равенство в своем изменяемом состоянии, то не ожидайте, что два экземпляра будут равны после того, как один из них изменился.

Я думаю, что бросок UnsupportedOperation нарушает спринт равных. Состояния равенства объекта:

Метод equals для класса Object реализует наиболее разборчивое возможное отношение эквивалентности для объектов; то есть для любых ненулевых ссылочных значений x и y этот метод возвращает истину тогда и только тогда, когда x и y относятся к одному и тому же объекту (x == y имеет значение "истина").

Итак, я должен иметь возможность вызывать равенства и получать истинное или ложное значение в зависимости от определения равенства объекта или переопределенного определения равенства.

6
ответ дан 1 December 2019 в 12:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: