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 помещает файл класса в тот же каталог, что и исходный файл.

последний бит жирным шрифтом является источником большой путаницы для начинающих и является частью вашей собственной проблемы.

таким образом, у вас есть две альтернативы:

  1. в вашем случае это нормально, если вы предоставляете текущий каталог в качестве целевого каталога, например (точка . означает текущей директории):

    javac -d . Hello.java
    

    если вы вызовете компилятор таким образом, он создаст com каталог для вас и поместите в него скомпилированный файл класса так, как программа java ожидает его найти. Затем, когда вы запускаете java, как указано выше, из c:\tmpJava ваша программа должна выполнить.

  2. вы можете настроить свой исходный код, используя структуру каталогов, которая отражает ваш структура пакета: поместите исходный файл Здравствуйте.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


выполните следующую команду

java -cp . com.Hello

java-classpath c:\tmpjava com.Привет