新的java / android:类加载器vs导入

时间:2014-08-14 12:25:48

标签: java android

如果我正确理解了类加载器,它会在运行时从jar文件加载一个类。如果这是真的,我认为我们可以使用import语句(在构建路径中包含jar文件之后)在没有类加载器的情况下轻松完成此操作。这是一个例子:

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;

因此我不明白类加载器的目的是什么。有人可以解释一下吗?

3 个答案:

答案 0 :(得分:4)

import用于正确的编译代码。假设您使用的是ArrayList,您必须通过指定ArrayList告诉编译器您正在使用哪个import java.util.ArrayList;,或者您可以直接使用

java.util.ArrayList al = new java.util.ArrayList(); 

不导入任何内容。

ClassLoaders在运行时使用。如果在运行时期间需要一个类,那么它将被ClassLoaders

加载到运行时环境(JVM)中

注意:import语句说 - 我将这个类用于编译器。 ClassLoaders用于动态类(ArrayList或任何其他类)加载到JVM中。

编辑:

假设您有2件衬衫(衬衫=类)一件红色带黑色条纹,另一件红色带白色条纹。现在,你告诉你的妈妈(编译器),请熨烫红色衬衫,你的妈妈问你告诉哪件红色衬衫带有白色条纹的红色衬衫。请注意,您实际上并不是使用这件衬衫,而只是告诉您将使用哪种红色衬衫。 第二天,你需要上大学,所以你告诉你爸爸给我带红色衬衫的白色条纹(爸爸就像ClassLoader),你穿上这件衬衫。 (类被加载并被使用)

答案 1 :(得分:0)

您不能使用import语句来加载类。事实上,import语句不是任何东西,它们只是语法糖,所以你可以在引用代码中的类时省略包。

示例:

import java.util.ArrayList;  // ArrayList will now refer to java.util.ArrayList in this code file.

// Using the shorthand provided by the import statement:
ArrayList myList1 = new ArrayList();

// Without using the shorthand provided by the import statement:
java.util.ArrayList myList2 = new java.util.ArrayList();

程序使用的每个类都必须由类加载器加载。 java rumtime环境提供了一个通常使用的默认类加载器。因此,代码第一次遇到创建新ArrayList的语句时,它将从类加载器中获取类定义。

类加载器还可以使用完整的类名称动态加载类(例如"java.util.ArrayList")。如果您实例化其他类加载器,您可以让它们中的每一个加载具有相同名称的类。这意味着如果类更改,您可以在新的类加载器中加载它的新版本。

应用程序服务器(如GlassFish或JBoss)使用加载同一类的多个版本的技术,以便您可以重新部署应用程序而无需重新启动应用程序服务器。此外,同一应用程序服务器中的不同应用程序可以使用不同版本的类。

示例:

假设您已经开发了一个User类,该类由同一应用程序服务器中部署的2个不同应用程序使用。您希望部署新版本的应用程序1,它使用新版本的User类。

答案 2 :(得分:0)

TheLostMind很好地描述了import语句。

要稍微扩展类加载器,想象一下你有一个类

class Foo {
    static Object foo() {
        return new java.util.ArrayList();
    }
}

在运行时,当调用foo()时,它会隐式使用自己的类加载器来加载其他类。请注意,在应用程序在运行时实际使用它之前,ArrayList类实际上并未加载到内存中!所以它等同于以下使用反射的代码:

public class Foo {
    static Object foo() throws ReflectiveOperationException {
        Class<?> arrayListClass = Class.forName("java.util.ArrayList", false, Foo.class.getClassLoader());
        return arrayListClass.getConstructor().newInstance();
    }
}

每当你使用反射时(例如在反序列化库和SPI工厂中),你必须明确使用哪个类加载器。

大多数人不使用多个类加载器,因为加载您的类的SystemClassLoader也能够加载所有依赖项(只要您的java CLASSPATH包含您在编译时使用的相同库。 javac CLASSPATH)。人们使用类加载器来创建允许在运行时加载插件的应用程序(例如使用OSGi模块的Eclipse)和允许在运行时加载应用程序的框架(例如Java EE和servlet)。对于大型应用程序,Android中有时也需要使用多个类加载器;见Custom Class Loading in Dalvik