两个URI对象相等,但它们的toString()不相同

时间:2018-04-12 12:20:01

标签: java file path java-8 uri

我不明白为什么两个文件' 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()输出。

3 个答案:

答案 0 :(得分:1)

URI#toString()方法记录良好here

  

以字符串形式返回此URI的内容。   如果此URI是通过调用此类中的一个构造函数创建的,则返回等效于原始输入字符串的字符串,或者根据需要返回从最初给定的组件计算的字符串。否则,此URI是通过规范化,解析或相对化创建的,因此根据RFC 2396第5.2节第7步中指定的规则从此URI组件构造字符串。

意思是,toString()方法的结果取决于我们初始化URI对象的方式(总共5 constructors。)

在这种情况下,您尝试以两种不同的方式初始化2个URI对象,以便toString()的结果不同。可以尝试normalize()方法。

答案 1 :(得分:0)

没有这样的合同,好像两个对象等于字符串表示需要相同。 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

之前尝试使用normalize方法

答案 2 :(得分:0)

似乎equals方法验证它们仅指向相同的资源。但是,统一资源标识符字符串是不同的,因为它们以两种不同的方式访问同一资源。

这就像去一家商店买1美元的1美元汽油或4个季度的硬币:你可以通过不同的方式获得相同的苏打水。收银员的人说,无论哪种方式支付都同样好,虽然他知道账单和一堆硬币之间存在明显区别。