【问题标题】:Why does Path.relativize behave differently on Java 8 and Java 11?为什么 Path.relativize 在 Java 8 和 Java 11 上的行为不同?
【发布时间】:2020-09-13 16:02:14
【问题描述】:
为什么relativize 方法在java-8 和java-11 上的行为不同?
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 描述是相同的。我觉得java-11 方式对我来说是正确的行为:
-
path1: /a/./b/../image.png 归一化为 /a/b/../image.png 归一化为 /a/image.png
-
path2: /a/file.txt
- 从
/a/image.png 和/a/file.txt导航的方式是../file.txt
问题
-
java-8 方式应该如何计算?它不会规范化路径吗?我不明白如何从head获取结果。
-
为什么这两个版本之间存在根本没有记录的差异?
【问题讨论】:
标签:
java-8
java-11
java-8
java-11
java-11
java-8
java
java-8
path
java-11
nio2
【解决方案1】:
【讨论】:
-
有趣的是,这已在 2010 年被报告为 JDK-6925169,但显然从未修复(仅在 2018 年解决为“重复”)。
【解决方案2】:
此处提供基于 Windows 的源代码答案。
从java-11 中的源代码观察(让我们看看sun.nio.fs.WindowsPath,Path 的实现之一)与@987654322 相比具有额外的代码,包括规范化 @。
后一种实现的关键行从411行开始,所以基本上,后一种实现在计算相对路径之前规范化路径:
WindowsPath base = this;
if (base.hasDotOrDotDot() || child.hasDotOrDotDot()) {
base = base.normalize();
child = child.normalize();
}
进一步挖掘,jdk8-b120(源)和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
java-8 方式应该如何计算?它不会规范化路径吗?我不明白如何从head获取结果。
最直接的方法是先规范化两条路径,然后再将它们相对化。但我不知道它是否完全涵盖了所有java.nio.file.Path 实现并且这样做是否安全。
Path path = path1.normalize().relativize(path2.normalize());