При динамической загрузке класса, когда целесообразно использовать
Class.forName("SomeClass");
и когда следует использовать
ClassLoader.getSystemClassLoader().loadClass("SomeClass");
Или это два способа сделать одно и то же?
При динамической загрузке класса, когда целесообразно использовать
Class.forName("SomeClass");
и когда следует использовать
ClassLoader.getSystemClassLoader().loadClass("SomeClass");
Или это два способа сделать одно и то же?
Они совершенно разные!
Как указано в документации для Class.forName(String)
,
Возвращает объект класса, связанный с классом или интерфейсом, с заданным именем строки. Вызов этого метода эквивалентен:
Class.forName(className, true, currentLoader)
(true
здесь означает, хотите ли вы инициализировать класс?)
С другой стороны, ClassLoader.loadClass(String)
:
Вызов этого метода эквивалентен вызову
loadClass(name, false)
.
(здесь логическое значение не имеет ничего общего с инициализацией, но если вы проверите документацию loadClass (String, boolean), вы увидите, что все, что он делает, это загрузить класс, а не инициализировать его).
Первый (Class.forName("SomeClass");
) будет:
Другой (ClassLoader.getSystemClassLoader().loadClass("SomeClass");
) будет:
Предположим, что вы кодируете веб-приложение, которое будет выполняться в контейнере, таком как Tomcat. То, что делает Tomcat, создает загрузчик классов для каждого веб-приложения (чтобы он мог выгрузить Webapps позже и освободить память - для этого вам нужен специальный загрузчик классов!). В этой ситуации вы можете видеть, что оба вызова дают совершенно разные результаты!
Для получения более подробной (и достоверной) информации о загрузке и инициализации классов, проверьте разделы 12.2 и 12.4 последнего (третьего) выпуска Спецификации языка Java.
Class.forName()
использует загрузчик классов caller и инициализирует класс (запускает статические инициализаторы и т.д.)
loadClass
- это метод ClassLoader
, поэтому он использует явно загруженный загрузчик и инициализирует класс лениво (при первом использовании).
Обратите внимание, что существует Class.forName(), который также принимает ClassLoader
.
Они в основном делают то же самое. Используемый ClassLoader может быть другим. Class.forName использует ClassLoader, который вы получаете из this.getClass(). GetClassLoader(), тогда как ваш другой код указывает на загрузку системного класса.
В большинстве приложений это будет тот же загрузчик классов, но в более сложных средах, таких как приложение J2EE или апплет, это может быть не так.
ClassLoader - абстрактный класс, однако ваше приложение всегда загружается загрузчиком классов, могут быть пользовательские загрузчики классов, такие как сетевой загрузчик классов или любой другой источник.
С другой стороны, класс сам по себе представляет классы и интерфейсы, а класс Class имеет функцию forName, которая использует текущий загрузчик классов, в котором ваше приложение работает по умолчанию для загрузки класса.
Вот источник для Class.forName, который, в свою очередь, вызывает вызывающий загрузчик классов.
public static Class<?> forName(String className)
throws ClassNotFoundException {
return forName0(className, true, ClassLoader.getCallerClassLoader());
}
http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/ClassLoader.html
http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Class.html#forName(java.lang.String)
Подсказка: Первоначальный загрузчик классов http://docs.oracle.com/javase/1.4.2/docs/guide/security/spec/security-spec.doc5.html
Class.forName()
загрузить и инициализировать класс. В подсистеме загрузчика классов он выполняет все три фазы, то есть нагрузки, связи и инициализации фаз.
ClassLoader.loadClass()
, которое задерживает инициализацию до тех пор, пока класс не будет использоваться в первый раз. В подсистеме загрузчика классов он выполняет только две фазы, то есть нагрузки и фазы связи.
Например:
class MyClass {
static {
System.out.println("static block in MyClass");
}
}
public class TestCase1 {
public static void main(String... args) throws Throwable {
Class.forName("A");
}
} //The above TestCase1 produce output: static block in MyClass
public class TestCase2 {
public static void main(String... args) throws Throwable {
ClassLoader.getSystemClassLoader().loadClass("MyClass");
}
} //The above TestCase2 not produce any output
Мне нравится загрузка класса в java...
Это зависит от того, в каком контексте выполняется приложение. Вы получите разные результаты, если используете его из веб-контекста, а не только из командной строки.
У меня также возникают проблемы в зависимости от того, как выглядит ваш ClassPath и чего я ожидал.
В этом статья JavaWorld подробно описывает это.