Два объекта URI равны, но их toString () - нет

Я не понимаю, почему два файла URI равны, но их String представление не равны. Это ошибка?

assertEquals(new File(".").toURI(), Paths.get(".").toUri()); // pass
assertEquals(new File(".").toURI().toString(), Paths.get(".").toUri().toString()); // fail

// org.opentest4j.AssertionFailedError: 
// Expected :file:/path/to/the/directory/./
// Actual   :file:///path/to/the/directory/./

ОБНОВЛЕНИЕ 1

Я понимаю, что технически вы можете полностью реализовать реализацию, в которой два объекта равны на основе метода equals, но имеют другой результат toString().

Однако мне просто любопытно, в случае класса URI, это хорошая реализация: два URI равны, но с разным строковым представлением.

В моем случае это другое, потому что есть разные результаты getAuthority(). Но тогда почему они равны? Это сбивает с толку. Если я не распечатал результат и не проверил его исходный код, я не узнаю об этом.

ОБНОВЛЕНИЕ 2

Согласно комментарию @VGR ниже, я провел еще один тест следующим образом:

    System.out.println(new File(".").toURI()); // file:/path/to/the/directory/./
    System.out.println(Paths.get(".").toUri()); // file:///path/to/the/directory/./
    System.out.println(new File(".").toURI().getAuthority()); // null
    System.out.println(Paths.get(".").toUri().getAuthority()); // null

Как видите, если мы получаем authority от обоих этих двух URI, то в обоих случаях это null.

Однако у них нет того же выхода toString().

Когда я создал эти URI, их строковые формы выглядели так же, как ваша, но оба они вернули null из своих соответствующих методов getAuthority(), как в Java 8, так и в Java 9. Итак, они действительно равны.

VGR 12.04.2018 15:56

@VGR добавил ваш комментарий как ОБНОВЛЕНИЕ 2

fluency03 12.04.2018 16:06
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
2
271
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Нет такого контракта, как если бы два объекта равны, строковое представление должно быть одинаковым. Реализация Java equals не зависит от метода toString. например, экземпляры следующего класса равны, но у них нет одинакового представления toString.

public class Foo {

    private String value;

    @Override
    public boolean equals(Object obj) {
        return true;
    }

    @Override
    public String toString() {
        return "value";
    }
}

В вашем конкретном случае оба экземпляра URI равны, потому что они указывают на один и тот же путь, но строковое представление отличается, потому что один из них содержит избыточную информацию. Попробуйте использовать метод нормализовать перед toString

Ответ принят как подходящий

Метод URI#toString() хорошо документирован здесь:

Returns the content of this URI as a string. If this URI was created by invoking one of the constructors in this class then a string equivalent to the original input string, or to the string computed from the originally-given components, as appropriate, is returned. Otherwise this URI was created by normalization, resolution, or relativization, and so a string is constructed from this URI's components according to the rules specified in RFC 2396, section 5.2, step 7.

это означает, что результат метода toString() зависит от того, как мы инициализируем объект URI (всего 5 конструкторов.)

В этом случае вы пытаетесь инициализировать 2 объекта URI двумя разными способами, поэтому результаты toString() будут разными. Можете попробовать метод normalize().

Я понимаю. Но так не должно быть, правда? Это сбивает с толку

fluency03 12.04.2018 14:56

Похоже, что метод equals проверяет, что они указывают только на один и тот же ресурс. Однако Строка символов унифицированного идентификатора ресурса отличается, потому что они обращаются к одному и тому же ресурсу двумя разными способами.

Это все равно, что пойти в магазин и купить газировку за 1 доллар на 1 доллар или 4 четвертных монеты: вы получите доступ к одной и той же газировке, используя разные способы ее приобретения. Парень у кассы говорит, что заплатить в любом случае было бы одинаково хорошо, хотя он знает, что есть явная разница между купюрой и кучей монет.

Другие вопросы по теме