为什么 Path.relativize 在 Java 8 和 Java 11 上表现不同?

Why does Path.relativize behave differently on Java 8 and Java 11?

为什么方法 relativize and 上表现不同?

Path path1 = Paths.get("/a/./b/../image.png");
Path path2 = Paths.get("/a/file.txt");
Path path = path1.relativize(path2);
System.out.println(path);

两个版本的 JavaDoc 描述相同。我觉得 方式对我来说是正确的行为:

问题

  1. 的方式应该如何计算?它不会规范化路径吗?我不明白如何从 head.

    中得到结果
  2. 为什么这两个版本之间存在根本没有记录的差异?

也许这个错误会回答你的问题: https://bugs.openjdk.java.net/browse/JDK-8066943

这影响了包含 .或 .. 并已为 Java 9 修复。 这就是为什么您会看到 8 和 11 之间存在差异的原因。

Windows 基于 source-code 在这里回答。

观察 is has additional code including normalization compared to .

中的源码(先看sun.nio.fs.WindowsPathPath的实现之一)

后一个实现的关键行从411行开始,所以基本上,后一个实现规范化路径之前考虑计算相对路径:

WindowsPath base = this;
if (base.hasDotOrDotDot() || child.hasDotOrDotDot()) {
    base = base.normalize();
    child = child.normalize();
}

进一步挖掘,实现在 jdk8-b120 (source) and jdk-9+95(来源)之间发生变化。由于引入了模块化系统,两者 类 实现和位置不同:

  • Java 8 岁及以下:/jdk/src/windows/classes/sun/nio/fs/WindowsPath.java
  • Java 9 岁及以上:/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsPath.java

How is the way supposed to be calculated? Doesn't it normalize the path? I don't understand how to get the result from head.

最直接的方法是先规范化两条路径,然后再相对化它们。但我不知道它是否完全涵盖所有 java.nio.file.Path 实现并且这样做是否安全。

Path path = path1.normalize().relativize(path2.normalize());