Files.isSameFile判断两个路径是否指向同一文件系统实体(相同inode+设备号),默认解析软链接后比较目标文件;若需判断软链接文件自身是否相同,应使用NOFOLLOW_LINKS读取属性后比较fileKey()。

Files.isSameFile 判断的是两个 路径是否指向同一个文件系统实体(即相同的 inode + 设备号),不是比对内容或路径字符串。对软链接而言,它默认解析符号链接后比较目标文件,而不是比较链接本身。
关键行为:默认跟随软链接
调用 Files.isSameFile(path1, path2) 时:
- 如果
path1或path2是软链接,JVM 会先 解析(resolve)它指向的真实路径; - 再比较两个解析后的路径是否代表同一文件(通过
getCanonicalFile()类似逻辑,但底层走系统 stat); - 因此,若两个软链接指向同一个目标文件,
isSameFile返回 true; - 若两个软链接本身是不同文件(即使内容相同、指向相同目标),但它们是独立创建的两个链接文件,则
isSameFile(linkA, linkB)仍返回 false —— 因为链接文件自身在文件系统中是两个不同的 inode。
想比对“软链接文件自身”是否相同?不能直接用 isSameFile
如果你关心的是:这两个 Path 是否指向同一个软链接文件(即链接本身是否是同一个文件),那就要避免自动解析:
-
不推荐用
isSameFile,因为它总会解析; - 正确做法是用
Files.isSameFile(Files.readSymbolicLink(path1), Files.readSymbolicLink(path2))?❌ 不行 —— 这比的是目标路径字符串是否相同,不严谨(相对路径、./、/../ 等会导致误判); - 更可靠方式:先获取两个软链接文件自身的
BasicFileAttributes(不跟随),再比对其fileKey():Path link1 = Paths.get("a.link"); Path link2 = Paths.get("b.link"); // 不跟随链接,获取链接文件自身的属性 BasicFileAttributes attrs1 = Files.readAttributes(link1, BasicFileAttributes.class, LinkOption.NOFOLLOW_LINKS); BasicFileAttributes attrs2 = Files.readAttributes(link2, BasicFileAttributes.class, LinkOption.NOFOLLOW_LINKS); // 比较链接文件自身是否为同一实体 boolean sameLinkFile = Objects.equals(attrs1.fileKey(), attrs2.fileKey());注意:
fileKey()在大多数文件系统上返回唯一标识(如 inode+dev),返回null表示无法确定,此时可降级用Files.isSameFile或路径标准化后字符串比较(仅作辅助)。立即学习“Java免费学习笔记(深入)”;
常见误区与验证建议
- 不要用
path1.equals(path2)或path1.normalize().equals(path2.normalize())—— 路径字符串相同 ≠ 文件相同(比如硬链接、挂载点); - 测试时用
ln -s target.txt a.link和ln -s target.txt b.link创建两个独立软链接,它们指向相同目标但自身是不同文件; - 用
ls -li查看 inode 号,确认两个链接文件的 inode 是否一致(通常不一致),即可验证isSameFile(a.link, b.link)应该返回 false; - 而
isSameFile(a.link, "target.txt")会返回 true(因为解析后指向同一目标)。
总结:按需选择语义
明确你要比什么:
- “它们是否指向同一个真实文件?” → 用 默认的
Files.isSameFile(p1, p2); - “它们是不是同一个软链接文件(即链接本体)?” → 用
Files.readAttributes(..., NOFOLLOW_LINKS)+fileKey()比较; - “它们的符号链接目标路径字符串是否一样?” → 用
Files.readSymbolicLink(p1).equals(Files.readSymbolicLink(p2)),但要注意路径规范化问题(不推荐用于强一致性判断)。
- 不要用


















