Java не может найти основной класс
я написал следующий исходный файл Java (Hello.java
):
package com;
public class Hello {
public static void main(String[] args) {
System.out.println("Hello!");
}
}
я сохраняю это в C:/tmpjava/Hello.java
.
из командной строки, перейдите в этот каталог и выполните команду javac Hello.java
. Тогда я бегу dir
:
Hello.class
Hello.java
затем из того же каталога, который я только что запустил javac
С, я бегу java Hello.class
и
Exception in thread "main" java.lang.NoClassDefFoundError: Hello/class
Caused by: java.lang.ClassNotFoundException: Hello.class
at java.net.URLClassLoader.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
Could not find the main class: Hello.class. Program will exit.
что здесь происходит?!? Как javac
работать нормально, но не java
?
5 ответов
класс Hello
принадлежит пакет com
. Таким образом, полное имя вашего класса -com.Hello
. При вызове программы, использующей java в командной строке, необходимо указать полное имя класса, содержащего ваш main
метод и опустить .класс!--16-->, например:
java com.Hello
программе java нужно это полное имя класса, чтобы понять, какой класс вы имеете в виду.
но у вас есть другой проблема. Программа java находит пакеты, подпакеты и принадлежащие им классы с помощью файловой системы. Поэтому, если у вас есть структура пакета, как com.Hello
, программа java ожидает найти файл класса с именем Здравствуйте.класс!--16--> в папку com, например: com / Здравствуйте.класс!--16-->. На самом деле вы можете наблюдать это поведение в Exception
что вы видите; вы неправильно использовали Здравствуйте.класс!--16-->, который java интерпретирует как пакета имени Hello
и класс имени class
, и ищет структуру каталогов Привет/класс:
java.ленг.Ошибке типа noclassdeffounderror: Привет/класс
но компилятор javac не настройте эту структуру каталогов по умолчанию. Вижу документация для javac, но важный бит таков: когда вы делаете свои компиляции, вы можете указать место назначения каталог с помощью -d
флаг:
-D каталог
установить папку назначения для файлов класса. Каталог назначения должен уже существовать; javac не будет создавать каталог назначения. Если класс является частью пакета, javac помещает файл класса в подкаталог, отражающий имя пакета, создавая каталоги как необходимый. Например, если указать -d c:\myclasses и класс называется com.пакета mypackage.MyClass, тогда файл класса называется c:\myclasses\com\mypackage\MyClass - ... класс.
Если -d не указан, javac помещает файл класса в тот же каталог, что и исходный файл.
последний бит жирным шрифтом является источником большой путаницы для начинающих и является частью вашей собственной проблемы.
таким образом, у вас есть две альтернативы:
-
в вашем случае это нормально, если вы предоставляете текущий каталог в качестве целевого каталога, например (точка
.
означает текущей директории):javac -d . Hello.java
если вы вызовете компилятор таким образом, он создаст com каталог для вас и поместите в него скомпилированный файл класса так, как программа java ожидает его найти. Затем, когда вы запускаете java, как указано выше, из c:\tmpJava ваша программа должна выполнить.
-
вы можете настроить свой исходный код, используя структуру каталогов, которая отражает ваш структура пакета: поместите исходный файл Здравствуйте.java внутри каталога под названием com в вашем случае: c:\tmpJava\com\Hello.java. Теперь от c:\tmpJava вы можете запустить компиляцию javac следующим образом:
javac com\Hello.java
вы не предоставили
-d
флаг, но это нормально, потому что вы сами создали структуру каталогов и снова цитируете из документации выше:Если-d нет указанный javac помещает файл класса в тот же каталог, что и исходный файл.
опять же, когда вы запускаете java, как указано выше, ваша программа должна выполняться.
обратите внимание, что эта вторая альтернатива обычно используется программистами java: файлы исходного кода организованы в структуру каталогов, которая отражает структуру пакета.
в этом объяснении мы проигнорировали концепцию classpath. Вам также нужно будет понять, что для написания программ java, но в вашем случае просто компиляции программы в текущем каталоге - если вы следуете одной из двух альтернатив выше при компиляции вашего класса - вы можете уйти, не устанавливая путь к классам, потому что по умолчанию программа java имеет текущий каталог в качестве пути к классам. Еще одна цитата, на этот раз из документация для java:
-СР классов
укажите список каталоги, архивы JAR и архивы ZIP для поиска файлов классов. Записи пути к классу разделяются точкой с запятой (;). Указание-classpath или -cp переопределяет любой параметр переменной среды CLASSPATH.
если-classpath и-cp не используются и CLASSPATH не задан, путь к классу пользователя состоит из текущего каталога (.).
обратите внимание, что когда вы используете IDE как Eclipse для запуска кода java, это в основном обрабатывается для вы, но вы все равно столкнетесь с проблемами classpath.
синтаксис команды Java:
java [classname]
не
java [filename]
Java выглядит в своем classpath для класса имени, которое вы предоставили. Обычно путь к классам включает текущий каталог, поэтому:
java Hello
... найду Привет.класс в текущем каталоге и выполнить его метод main ().
однако, если класс находится где-то еще (например, в a .jar или где-то еще в файловой системе) вы можете указать это с переменной среды CLASSPATH или в командной строке:
java -cp build/classes Hello
java -cp build/jars/myjar.jar Hello
класс должен быть в C:\tmpjava\com\Hello.class
И вы должны бежать от C:\tmpjava
: java -cp . com.Hello
Когда вы помещаете класс в пакет, он определяет файловую структуру класса. Т. е. ваш класс который в пакете com
должен быть в папке com