Java 两个URI对象相等,但它们的toString()不相等
我不明白为什么两个文件的Java 两个URI对象相等,但它们的toString()不相等,java,file,path,java-8,uri,Java,File,Path,Java 8,Uri,我不明白为什么两个文件的URIs相等,但它们的String表示不相等。是虫子吗 assertEquals(new File(".").toURI(), Paths.get(".").toUri()); // pass assertEquals(new File(".").toURI().toString(), Paths.get(".").toUri().toString()); // fail // org.opentest4j.AssertionFailedError: // Expec
URI
s相等,但它们的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
是相等的,但具有不同的字符串表示形式
public class Foo {
private String value;
@Override
public boolean equals(Object obj) {
return true;
}
@Override
public String toString() {
return "value";
}
}
在我的例子中,它是不同的,因为有不同的getAuthority()
result。但是,为什么他们是平等的呢?这令人困惑。如果我没有打印出结果并检查其源代码,我将不会意识到这一点
更新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
如您所见,如果我们从这两个URI
s获得authority
,那么在这两种情况下都是null
但是,它们没有相同的
toString()
输出。没有两个对象相等的约定,字符串表示需要相同。Javaequals
实现独立于toString
方法。e、 下面类的g实例都是相等的,但它们没有相同的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()
方法有很好的文档记录:
以字符串形式返回此URI的内容。
如果此URI是通过调用此类中的一个构造函数创建的,那么将返回一个与原始输入字符串或从原始给定组件计算的字符串等效的字符串(视情况而定)。否则,该URI是通过规范化、解析或相对化创建的,因此根据RFC 2396第5.2节第7步中指定的规则,从该URI的组件构造一个字符串
也就是说,toString()
方法的结果取决于我们初始化URI对象的方式(总共)
在本例中,您试图以两种不同的方式初始化2个URI对象,因此
toString()
的结果是不同的。可以尝试此方法。看起来equals方法正在验证它们是否仅指向相同的资源。但是,统一资源标识符字符串是不同的,因为它们以两种不同的方式访问同一资源
这就像去商店用1美元的钞票或4个25美分的硬币买1美元的苏打水:你可以通过不同的方式获得相同的苏打水。收银机旁的那个家伙说,无论哪种支付方式都一样好,尽管他知道一张钞票和一堆硬币之间有着明显的区别 我明白。但它不应该是这样的,对吗?令人困惑的是,当我创建这些URI时,它们的字符串形式看起来与您的相同,但它们都从各自的
getAuthority()
方法返回null,这两种方法都使用Java 8和Java 9。所以,它们确实是相等的。@VGR将您的注释添加为更新2