java.lang.ClassNotFoundException для указанного класса
У меня в основном есть следующее утверждение
Class booki = Class.forName("Book");
который бросает java.lang.ClassNotFoundException
исключение
когда я использую полный путь, как Class booki = Class.forName("javatests.Book");
все в порядке.
Основной класс и класс Book находятся в одном пакете, я также пытался использовать import static javatests.Book.*;
но все равно выдает исключение, если я не установил полный путь javatests.Book
, Может кто-нибудь объяснить мне, почему?
5 ответов
Class.forName
разрешает полное имя класса в класс. Поскольку метод не знает, где он вызывается ни из пакета вызывающего класса, ни из import
s в вызывающем классе играют любую роль.
Из документов Class#forName
public static Class<?> forName(String className)
throws ClassNotFoundException
Параметры:
className - полное имя нужного класса.
Так что это не скинут ClassNotFoundException
Class booki = Class.forName("javatests.Book");
Например, не нужно импортировать java.lang.*
пакет в программе Java, но для загрузки класса Thread
от java.lang
пакет нужно написать
Class t = Class.forName("java.lang.Thread");
приведенный выше фрагмент кода возвращает дескриптор класса времени выполнения для класса с именем java.lang.Thread
JLS предоставляет следующее описание:
Поиск класса всегда выполняется от имени ссылающегося класса и выполняется через экземпляр
ClassLoader
, Учитывая полное имя класса, этот метод пытается найти, загрузить и связать класс.
JDK использует один экземпляр ClassLoader
который ищет набор корней дерева каталогов, указанных в переменной среды CLASSPATH; и, очевидно, он не знает о месте (пакете), которое он назвал. Вот почему ему нужно полное имя.
Во-первых, класс Book должен быть в пакете javatests.
JVM загружает класс по имени через путь к классу. В пути к классам нет класса с именем "Книга". Таким образом, JVM дает вам ClassNotFoundException, когда оправдывает Class.forName("Книга"). Но Class.forName("javatests.Book")'сообщает JVM, что класс с именем' Book 'находится в пакете'javatests'. Таким образом, JVM может найти его и загрузить.
Надеюсь мой ответ полезен:)
Вам всегда нужно квалифицированное имя класса, если оно не внутри одного пакета. Если я определю класс foo в моем пакете, я могу вызвать метод Class testClass = Class.forName("foo")
но я не могу позвонить Class testClass = Class.forName("SecureRandom");
даже если я импортирую SecureRandom. Вот как работает эта функция. Вероятно, у него есть ярлык, где он пытается найти что-то внутри локальных пакетов, но мало что делает за этим.