都可对类进行加载,返回Class对象(不是实例对象,Class对象是将.class文件加载到内存中,实例对象就是通常我们所说的new Object())
Class 中有两个重要方法:
forName(String className)
: 返回与带有给定字符串名的类或接口相关联的 Class
对象。
forName(String name, boolean initialize, ClassLoader loader)
: 使用给定的类加载器,返回与带有给定字符串名的类或接口相关联的 Class
对象。
源码如下(jdk1.6):
public static Class<?> forName(String paramString) throws ClassNotFoundException {
return forName0(paramString, true, ClassLoader.getCallerClassLoader());
}
public static Class<?> forName(String paramString, boolean paramBoolean, ClassLoader paramClassLoader)
throws ClassNotFoundException {
if (paramClassLoader == null) {
SecurityManager localSecurityManager = System.getSecurityManager();
if (localSecurityManager != null) {
ClassLoader localClassLoader = ClassLoader.getCallerClassLoader();//获取调用者类的加载器
if (localClassLoader != null) {
localSecurityManager.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
}
}
}
return forName0(paramString, paramBoolean, paramClassLoader);
}
private static native Class forName0(String paramString, boolean paramBoolean, ClassLoader paramClassLoader)
throws ClassNotFoundException;
只有 initialize
参数为 true
且以前未被初始化时,才初始化该类。
调用 forName("X") 将导致命名为 X 的类被初始化。
返回具有指定名的类的 Class
对象。
第一个方法等价于:
Class.forName(className, true, currentLoader)
其中类加载器通过下述方法获取,getCallerClassLoader方法返回--获得调用者类的加载器:
ClassLoader localClassLoader = ClassLoader.getCallerClassLoader();
故通常使用的Class.forName()除了将.class文件加载到内存中,还会对类进行初始化,执行static块中代码,如JDBC注册驱动。
ClassLoader中常用方法:
public Class<?> loadClass(String name) throwsClassNotFoundException:使用指定的 二进制名称来加载类。此方法使用与 loadClass(String, boolean) 方法相同的方式搜索类。Java 虚拟机调用它来分析类引用。调用此方法等效于调用 loadClass(name, false)。
protectedClass<?>loadClass(String name,boolean resolve) throwsClassNotFoundException :使用指定的 二进制名称来加载类。
此方法的默认实现将按以下顺序搜索类:
1、调用 findLoadedClass(String)
来检查是否已经加载类。 2、在父类加载器上调用 loadClass
方法。如果父类加载器为 null,则使用虚拟机的内置类加载器。 3、调用 findClass(String)
方法查找类。 如果使用上述步骤找到类,并且 resolve 标志为真,则此方法将在得到的 Class 对象上调用 resolveClass(Class)
方法。 鼓励用 ClassLoader 的子类重写 findClass(String)
,而不是使用此方法。
源码如下(jdk1.6):
public Class<?> loadClass(String paramString) throws ClassNotFoundException {
return loadClass(paramString, false);
}
protected synchronized Class<?> loadClass(String paramString, boolean paramBoolean) throws ClassNotFoundException {
Class localClass = findLoadedClass(paramString);
if (localClass == null) {
try {
if (this.parent != null)
localClass = this.parent.loadClass(paramString, false);
else {
localClass = findBootstrapClassOrNull(paramString);
}
} catch (ClassNotFoundException localClassNotFoundException) {
}
if (localClass == null) {
localClass = findClass(paramString);
}
}
if (paramBoolean) {
resolveClass(localClass);
}
return localClass;
}
故ClassLoader只将加载类到内存中,不会对类进行初始化。
Class中有个方法定义:加载由 libname
参数指定的系统库,最终被java native修饰的方法调用。
private static native Class forName0(String paramString,boolean paramBoolean, ClassLoader paramClassLoader)
throws ClassNotFoundException;
由此好奇该关键字的作用。
JNI:提供若干的API实现了Java和其它预言的通信(主要C&C++),称为Java Native Interface (Java本地接口)。
native的方法:java不用自己实现,是由C/C++语言实现且被编译成DLL,System.loadLibrary()方法加载该系统库,最终java native修饰的方法可调用DLL。
实际上java就是在不同的平台上调用不同的native方法实现对操作系统的访问的。