我不明白为什么两个文件' 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/./
我理解,从技术上讲,您可以完全实现,其中两个对象基于equals
方法相同,但结果不同toString()
。
但是,我只是好奇,在类URI
的情况下,它是一个很好的实现:两个URI
是相同的但具有不同的字符串表示。
在我的情况下,它是不同的,因为有不同的getAuthority()
结果。但那么,为什么他们是平等的?这令人困惑。如果我没有打印出结果并检查它的源代码,我就不会意识到这一点。
根据@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()
输出。
答案 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
答案 2 :(得分:0)
似乎equals方法验证它们仅指向相同的资源。但是,统一资源标识符字符串是不同的,因为它们以两种不同的方式访问同一资源。
这就像去一家商店买1美元的1美元汽油或4个季度的硬币:你可以通过不同的方式获得相同的苏打水。收银员的人说,无论哪种方式支付都同样好,虽然他知道账单和一堆硬币之间存在明显区别。