一、获取Class的方法
1.直接用(类名.class)
2.对象.getClass()
3.Class.forName("类的全限定名")
输出结果为:
c===>class [Ljava.lang.String;
c===>class [Ljava.lang.String;
c===>class [Ljava.lang.String;
我们看下其他的数组类名:
运行结果如下为:
系统默认的classloader如何获取?
ClassLoader.getSystemClassLoader()
从运行结果可以看到系统默认使用sun.misc.Launcher$AppClassLoader这个ClassLoader。
classloader加载类的方法:ClassLoader.loadClass(String className)
如下例子:
运行结果发现 已经调用sayHello方法了
二、自定义classloader
classloader加载顺序:
⑴首先执行一次检查,查看客户程序请求的类是否已经由当前的类装入器装入。如果是,则返回已装入的类,请求处理完毕。JVM缓冲了类装入器装入的所有类,已经装入的类不会被再次装入。
⑵如果尚未装入类,则装入类的请求被委托给父类装入器,这个操作发生在当前的类装入器尝试装入指定的类之前。委托装入类的操作一直向上传递,直至bootstrap类装入器,如前所述,bootstrap类装入器是处于树形结构的顶层,它不再有可委托的父类装入器。
⑶如果父类装入器未能装入指定的类,则当前的类装入器将尝试搜索该类。每一个类装入器有预定义的搜索和装入类的位置。例如,bootstrap类装入器搜索 sun.boot.class.path系统属性中指定的位置(包括目录和zip、jar文件),system类装入器搜索的位置由JVM开始运行时传入的CLASSPATH命令行变量指定(相当于设置java.class.path系统属性)。如果找到了类,则类装入器将类返回给系统,请求处理完毕。
[b]三、classloader的命名空间[/b]
*在JVM当中,ClassLoader会被当成命名空间来分隔各自加载的类*
# 项目中可以使用不同的ClassLoader来加载包名、类名完全相同的Class,但是这两个Class的内容可以完全不一样。
# 即使是同一个Class文件,如果被两个不同的ClassLoader来加载,那么在JVM中它们相互独立,不算是同一个Class。
第一种情况我们可能会经常遇到,比如使用开源框架时,有的框架里面可以看到对同一个项目有多个不同版本的依赖,有的地方使用版本x,有的地方使用版本y,x与y的包名,类名都一样,但里面的内容可以已经不同,却可以相安无事,这就是由于它们运行在各自独立的ClassLoader当中
1.直接用(类名.class)
2.对象.getClass()
3.Class.forName("类的全限定名")
Class c = String[].class;
System.out.println("c===>"+c);
c = new String[1].getClass();
System.out.println("c===>"+c);
//JVM对Array的实际类名编码为: 左括号 + 类别代码 + 类名
try {
c = Class.forName("[Ljava.lang.String;");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
输出结果为:
c===>class [Ljava.lang.String;
c===>class [Ljava.lang.String;
c===>class [Ljava.lang.String;
我们看下其他的数组类名:
System.out.println("byte[]: " + byte[].class.getName());
System.out.println("char[]: " + char[].class.getName());
System.out.println("int[]: " + int[].class.getName());
System.out.println("long[]: " + long[].class.getName());
System.out.println("double[]: " + double[].class.getName());
System.out.println("float[]: " + float[].class.getName());
运行结果如下为:
byte[]: [B
char[]: [C
int[]: [I
long[]: [J
double[]: [D
float[]: [F
系统默认的classloader如何获取?
ClassLoader.getSystemClassLoader()
从运行结果可以看到系统默认使用sun.misc.Launcher$AppClassLoader这个ClassLoader。
classloader加载类的方法:ClassLoader.loadClass(String className)
如下例子:
public class User {
private String name;
private Integer age;
public User(String name, Integer age) {
super();
this.name = name;
this.age = age;
}
public User() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public void sayHello()
{
System.out.println("Hello,I am "+name+","+age+" years old.");
}
}
//测试类中的方法
private static void test2()
{
ClassLoader cl= ClassLoader.getSystemClassLoader();
System.out.println("cl===> " + cl);
try {
Class clazz = cl.loadClass("com.test.jvm.classloader.User");
User user =(User)clazz.newInstance();
user.sayHello();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
System.out.println("class com.test.jvm.classloader.User not found!");
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
运行结果发现 已经调用sayHello方法了
二、自定义classloader
classloader加载顺序:
⑴首先执行一次检查,查看客户程序请求的类是否已经由当前的类装入器装入。如果是,则返回已装入的类,请求处理完毕。JVM缓冲了类装入器装入的所有类,已经装入的类不会被再次装入。
⑵如果尚未装入类,则装入类的请求被委托给父类装入器,这个操作发生在当前的类装入器尝试装入指定的类之前。委托装入类的操作一直向上传递,直至bootstrap类装入器,如前所述,bootstrap类装入器是处于树形结构的顶层,它不再有可委托的父类装入器。
⑶如果父类装入器未能装入指定的类,则当前的类装入器将尝试搜索该类。每一个类装入器有预定义的搜索和装入类的位置。例如,bootstrap类装入器搜索 sun.boot.class.path系统属性中指定的位置(包括目录和zip、jar文件),system类装入器搜索的位置由JVM开始运行时传入的CLASSPATH命令行变量指定(相当于设置java.class.path系统属性)。如果找到了类,则类装入器将类返回给系统,请求处理完毕。
[b]三、classloader的命名空间[/b]
*在JVM当中,ClassLoader会被当成命名空间来分隔各自加载的类*
# 项目中可以使用不同的ClassLoader来加载包名、类名完全相同的Class,但是这两个Class的内容可以完全不一样。
# 即使是同一个Class文件,如果被两个不同的ClassLoader来加载,那么在JVM中它们相互独立,不算是同一个Class。
第一种情况我们可能会经常遇到,比如使用开源框架时,有的框架里面可以看到对同一个项目有多个不同版本的依赖,有的地方使用版本x,有的地方使用版本y,x与y的包名,类名都一样,但里面的内容可以已经不同,却可以相安无事,这就是由于它们运行在各自独立的ClassLoader当中