Почему `javac -cp` не нуждается в `.`, в то время как `java -cp` нуждается?

#java #javac

#java #javac

Вопрос:

У меня есть два вопроса:

Почему javac -cp не нужен . ?

 $ javac -cp /home/t/programs/java/test/junit-4.11.jar TestCase.java
  

Почему java -cp нужно . ?

 $ java -cp /home/t/programs/java/test/junit-4.11.jar:/home/t/programs/java/test/hamcrest-core-1.3.jar org.junit.runner.JUnitCore TestCase
JUnit version 4.11
Could not find class: TestCase

Time: 0.002

OK (0 tests)

$ java -cp .:/home/t/programs/java/test/junit-4.11.jar:/home/t/programs/java/test/hamcrest-core-1.3.jar org.junit.runner.JUnitCore TestCase
JUnit version 4.11
.running TestCase test1
.running TestCase test2

Time: 0.023

OK (2 tests)
  

TestCase.java:

 import static org.junit.Assert.*;
import org.junit.Test;

// define a test case class, whose instances represent test cases
public class TestCase {

  @Test
  public void test1() {
      System.out.println("running TestCase test1");
      assertTrue(true);
  }

  @Test
  public void test2() {
      System.out.println("running TestCase test2");
      assertTrue(true);      
  }

}
  

Комментарии:

1. Это нулевой процент реального ответа, но: Java 1 была срочной работой, и они кое-что перепутали. Меня не удивило бы, если бы это несоответствие было просто тем, что они либо не заметили, либо не было высокоприоритетным исправлением. И затем, когда он вышел, они не захотели его менять.

2. @yshavit Нет, это совершенно непротиворечиво, просто причины не очень хорошо объяснены. Или вообще вообще.

Ответ №1:

Поскольку javac обрабатывает файлы, java обрабатывает полные имена классов.

Редактировать

Чтобы немного расширить, когда вы компилируете, вы передаете файлы, которые хотите скомпилировать напрямую javac , поэтому путь к классу предназначен только для того, чтобы содержать пакеты, необходимые для компиляции файлов, которые вы передаете в качестве аргумента. То есть файл, который вы компилируете, не обязательно должен находиться в пути к классу.

С другой стороны, когда вы выполняете with java , вы сообщаете JVM «запустите этот класс из classpath». Конечно, путь к классу по умолчанию . равен . Но затем вы решили указать пользовательский путь к классу с -cp помощью , который не добавляет к пути к классу, а проверяет его. Поэтому вы должны добавить его обратно явно.

Смотрите Последний раздел официального руководства для подтверждения.

Комментарии:

1. неправильно говорить, что обрабатывает пакеты и классы , более правильным способом было бы обрабатывать полные имена классов

Ответ №2:

. быть частью пути к классу компилятора является результатом нескольких вещей, происходящих неявно. Для возможности компиляции сгенерированные классы, на которые ссылаются в других классах, должны быть доступны через classpath . Таким образом, компилятор добавляет путь к файлу назначения класса к пути к классу. Если вы не предоставляете ничего конкретного, этот каталог является исходным каталогом. Если вы не укажете, что конкретно используется рабочий каталог процесса, который используется по умолчанию . .

Вызов javac -help показывает вам различные возможные настройки:

 "c:Program FilesJavajdk1.8.0_181binjavac.exe" -help
Usage: javac <options> <source files>
where possible options include:
  -g                         Generate all debugging info
  -g:none                    Generate no debugging info
  -g:{lines,vars,source}     Generate only some debugging info
  -nowarn                    Generate no warnings
  -verbose                   Output messages about what the compiler is doing
  -deprecation               Output source locations where deprecated APIs are used
  -classpath <path>          Specify where to find user class files and annotation processors
  -cp <path>                 Specify where to find user class files and annotation processors
  -sourcepath <path>         Specify where to find input source files
  -bootclasspath <path>      Override location of bootstrap class files
  -extdirs <dirs>            Override location of installed extensions
  -endorseddirs <dirs>       Override location of endorsed standards path
  -proc:{none,only}          Control whether annotation processing and/or compilation is done.
  -processor <class1>[,<class2>,<class3>...] Names of the annotation processors to run; bypasses default discovery process
  -processorpath <path>      Specify where to find annotation processors
  -parameters                Generate metadata for reflection on method parameters
  -d <directory>             Specify where to place generated class files
  -s <directory>             Specify where to place generated source files
  -h <directory>             Specify where to place generated native header files
  -implicit:{none,class}     Specify whether or not to generate class files for implicitly referenced files
  -encoding <encoding>       Specify character encoding used by source files
  -source <release>          Provide source compatibility with specified release
  -target <release>          Generate class files for specific VM version
  -profile <profile>         Check that API used is available in the specified profile
  -version                   Version information
  -help                      Print a synopsis of standard options
  -Akey[=value]              Options to pass to annotation processors
  -X                         Print a synopsis of nonstandard options
  -J<flag>                   Pass <flag> directly to the runtime system
  -Werror                    Terminate compilation if warnings occur
  @<filename>                Read options and filenames from file
  

Параметры, на которые я ссылался, — это -s и -sourcepath . -cp используется для определения дополнительных местоположений (каталогов и файлов библиотеки), где компилятор может искать уже скомпилированные классы. Это также значение -cp при вызове java , поэтому между этими двумя исполняемыми файлами нет противоречия.