Создание пути между двумя путями в Java с использованием класса Path

Что именно означает это предложение из this oracle java tutorial:

Относительный путь не может быть построен, если только один из путей включает корневой элемент. Если оба пути включают корневой элемент, возможность построения относительного пути зависит от системы.

С "системным различием" они означают только то, что, если элемент содержит корень, он будет работать только в написанном на платформе конкретном синтаксисе? Я думаю, это единственное, что они имеют в виду. Есть ли другие способы чтения этого?

например:

public class AnotherOnePathTheDust {
    public static void main (String []args)
    {
    Path p1 = Paths.get("home");
    Path p3 = Paths.get("home/sally/bar"); //with "/home/sally/bar" i would get an exception.
    // Result is sally/bar
    Path p1_to_p3 = p1.relativize(p3);
    // Result is ../..

    Path p3_to_p1 = p3.relativize(p1);
    System.out.println(p3_to_p1);   }
}

Исключением, которое я получаю с помощью "/home/sally/bar" вместо "home/sally/bar" (без root), является следующее:

 java.lang.IllegalArgumentException: 'other' is different type of Path

Почему это не работает? каков конфликт с системой, что они означают?

Ответ 1

Потому что p1 и p3 имеют разные корни.

Если вы используете "/home/sally/bar" вместо "home/sally/bar" для p3, то p3.getRoot() вернет /, но p1.getRoot() будет нулевым.

Вы узнаете, почему вы получили это исключение, прочитав следующие коды (взято из http://cr.openjdk.java.net/~alanb/6863864/webrev.00/src/windows/classes/sun/nio/fs/WindowsPath.java-.html Line374-375):

// can only relativize paths of the same type
if (this.type != other.type)
     throw new IllegalArgumentException("'other' is different type of Path");

Ответ 2

Системная зависимость здесь относится к конкретной реализации ОС, которую я бы предположил. Таким образом, Linux будет обрабатывать это иначе, чем Windows, и т.д. Без корневых путей (т.е. Путей, начинающихся с /), оба пути считаются братьями и сестрами, сидящими на одном уровне (то есть в /home/sally ). Поэтому, когда вы пытаетесь релятивизировать, если они не находятся на одном уровне, нет никакой гарантии, где хранится не-корневой путь, что имеет смысл, если вы думаете об этом. Помогает ли это?

Ответ 3

Я провел несколько тестов вашего примера. Фактически исключение, о котором вы упоминаете, появляется только тогда, когда один из путей содержит корень, а другой нет (точно так же, как сказано в предложении). Например:

  • /дома/выходка/бар
  • дома

Он работает нормально, если оба пути содержат корни. "Системная зависимость" означает, вероятно, такой случай в Windows:

  • C:\дом
  • D:\главная\вылазка\бар

Выше приведено следующее исключение:

java.lang.IllegalArgumentException: 'other' has different root

Вы никогда не столкнетесь с чем-то подобным (исключение для обоих путей, содержащих корневые абсолютные пути) в Unix

Ответ 4

Как уже упоминалось, это связано с разными корнями в пути.

Чтобы обойти это, вы можете использовать toAbsolutePath().

Например:

public class AnotherOnePathTheDust {
  public static void main (String []args)
  {
    Path p1 = Paths.get("home").toAbsolutePath();
    Path p3 = Paths.get("/home/sally/bar").toAbsolutePath();

    Path p1_to_p3 = p1.relativize(p3);

    Path p3_to_p1 = p3.relativize(p1);
    System.out.println(p3_to_p1);
  }
}