1.类的加载过程:
程序经过java.exe命令以后,回生成一个或多个字节码文件(.class),接着我们使用java.exe命令堆某个字节码文件解释运行,相当于将某个字节码文件加载到内存中。此过程就叫做类的加载过程。加载到内存中的类,我们就称作运行时类,此运行时类,就作为class的一个实例。
获取Class类实例的方式:
public class PersonTest {
//获取class实例的方式
@Test
public void test1() throws ClassNotFoundException{
//方式一:调用运行时类的属性:.class
Class clazz1 = Person.class;
System.out.println(clazz1);
//方式二:通过运行时类的对象,调用getClass()
Person p1 = new Person();
Class clazz2 = p1.getClass();
System.out.println(clazz2);
//方式三:调用Class的静态方法:forName(String classPath)
Class clazz3 = Class.forName("com.flect.Person");
System.out.println(clazz3);
System.out.println(clazz1 == clazz3);//加载到内存中的运行时类,会缓存一段时间,在此期间,我们可以通过不同的方式来获取此运行时类
System.out.println(clazz2 == clazz3);
//方式四:使用类的加载器:ClassLoader
ClassLoader classLoader = PersonTest.class.getClassLoader();
Class clazz4 = classLoader.loadClass("com.flect.Person");
System.out.println(clazz4);
System.out.println(clazz1 == clazz4 );
}
}
那些对象可以有Class对象?
1>class:外部类,成员(成员内部类,静态内部类),局部内部类,匿名内部类
2>interface:接口
3>[]:数组
4>enum:枚举
5>annotation:注解@interface
6>primitive type:基本数据类型
7>void
2.ClassLoader
类加载器作用:是用来把类装进内存。
引导类加载器:用c++编写的,是JVM自带的类加载器,负责java平台核心库,用来装载核心类库。该类加载器无法直接获取
扩展类加载器:负责jre/lib/ext目录下jar包或-D java.ext.dirs指定目录下的jar包装入工作库
系统类加载器:负责java-classpath或-D java.class.path所指的目录下的类与jar包装入工作,是常用的加载器。
public void test2(){
//对于自定义,使用系统类加载器进行加载
ClassLoader classLoader = PersonTest.class.getClassLoader();
System.out.println(classLoader);
//调用系统类加载器的getParent():获取扩展类加载器
ClassLoader classLoader1 = classLoader.getParent();
System.out.println(classLoader1);
//调用扩展类加载器的getParent():无法获取引导类加载器
//引导类加载器主要负责加载java的核心类库,无法加载自定义类的
ClassLoader classLoader2 = classLoader1.getParent();
System.out.println(classLoader2);
}
properties与classloader加载配置文件:
public void test3() throws Exception{
Properties pros = new Properties();
//方式一:读取配置文件
FileInputStream fis = new FileInputStream("out//jdbc.properties");
pros.load(fis);
//方式二:使用ClassLoader,默认识别为当前module的src下
// ClassLoader classLoader = PersonTest.class.getClassLoader();
// InputStream is = classLoader.getResourceAsStream("out//jdbc.properties");
// pros.load(is);
String user = pros.getProperty("user");
String password = pros.getProperty("password");
System.out.println("user:"+user+"password:"+password);
}
}
3.通过反射创建运行时类的对象
public void test4() throws Exception{
//通过发射创建运行时类的对象
Class clazz = Person.class;
//newInstance():调用此方法,创建对应的运行时类的对象,内部调用了类的空参构造器
// 要想此方法能创建对象,运行是类必须提供空参构造器
// 空参构造器的权限是public
Person obj = (Person) clazz.newInstance();
System.out.println(obj);
}
在javabean中提供一个空参构造器,原因:
1.便于通过反射创建运行时类对象
2.便于子类继承此运行时类时,磨粉调用super()时,保证父类有此构造器
4.反射的动态性
public void test5() throws Exception{
int num = (int)Math.random()*3+1;
String classPath = "";
switch (num){
case 0:
classPath = "java.util.Date";
break;
case 1:
classPath = "java.lang.Object";
break;
case 2:
classPath = "java.lang.Math";
break;
}
Object obj = getInstance(classPath);
System.out.println(obj);
}
// 创建一个指定类的对象,classPath:指定类的全类名
public Object getInstance(String classPath) throws Exception{
Class clazz = Class.forName(classPath);
return clazz.newInstance();
}
5.获取运行时类的完整结构
获取运行时类的带泛型的父类的泛型 genericSuper()
获取运行时类的接口 getInterfaces()
获取运行时类的父类的接口 getSuperclass().getInterfaces()
获取运行时类所在的包 clazz.getPackage()
获取运行时类声明的注解 clazz.getAnnotations()
6.调用运行时类的指定结构,属性,方法
public void test6() throws Exception{
Class clazz = Person.class;
//获取运行时类的对象
Person p = (Person) clazz.newInstance();
//常用,获取指定变量名的属性
Field name = clazz.getDeclaredField("name");
name.setAccessible(true);
//设置当前属性的值set():参数1指明设置哪个对象的属性,参数2将此属性值设置为多少
name.set(p,100);
//获取当前属性值
int pid = (int) name.get(p);
//获取某个指定的方法,getDeclaredMethod():参数一指明获取方法的名称,参数2指明获取的方法的形参列表
Method show = clazz.getDeclaredMethod("show",String.class);
//保证当前方法时可访问的
show.setAccessible(true);
//调用invoke():参数1:方法的调用者,参数2:给方法的形参赋值的实参,它的返回值即为对应类调用方法的返回值
Object returnValue = show.invoke(p,"CHN");
System.out.println(returnValue);
//调用静态方法
Method showdesc = clazz.getDeclaredMethod("showDesc");
showdesc.setAccessible(true);
Object returnVal = show.invoke(Person.class,"CHN");
//获取指定的构造器:getDeclaredCocstructor()参数指明构造器的参数列表
Constructor c clazz.getDeclaredCocstructor(String.class);
c.setAccessible(true);
Peerson per = (Person) c.newInstanse("Tom");
}