1.概念
在程序运行过程中分析类的一种能力(描述类的类)
2.作用
- 分析类
- 加载并初始化一个类
- 查看类的所有属性和方法
- 查看并使用对象
- 查看一个对象的所有属性和方法
- 使用对象的任意属性和方法
类加载器(ClassLoader)
类装载器是用来把类(class)装载进 JVM 的。JVM 规范定义了两种类型的类装载器:启动类装载器(bootstrap)和用户自定义装载器(user-defined class loader)。 JVM在运行时会产生3个类加载器组成的初始化加载器层次结构
public class ReflectionTest {
@Test
public void testClassLoader() throws ClassNotFoundException, FileNotFoundException{
//1. 获取一个系统的类加载器(可以获取,当前这个类PeflectTest就是它加载的)
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
System.out.println(classLoader);
//2. 获取系统类加载器的父类加载器(扩展类加载器,可以获取).
classLoader = classLoader.getParent();
System.out.println(classLoader);
//3. 获取扩展类加载器的父类加载器(引导类加载器,不可获取).
classLoader = classLoader.getParent();
System.out.println(classLoader);
//4. 测试当前类由哪个类加载器进行加载(系统类加载器):
classLoader = Class.forName("com.reflect.ReflectionTest") .getClassLoader();
System.out.println(classLoader);
//5. 测试 JDK 提供的 Object 类由哪个类加载器负责加载(引导类)
classLoader = Class.forName("java.lang.Object") .getClassLoader();
System.out.println(classLoader);
}
}
//结果:
sun.misc.Launcher$AppClassLoader@18b4aac2
sun.misc.Launcher$ExtClassLoader@326de728
null
sun.misc.Launcher$AppClassLoader@18b4aac2
null
负责将类的字节码文件(.class文件)加载到内存中,并生成对应的Class对象
Class对象
java.lang.Class类的对象,也叫字节码文件对象,每个Class对象对应一个字节码文件
类的加载时机
1).创建实例对象
Person person = new Person();
2).访问类的静态成员
Calendar.getInstance();
3).初始化子类
class User extends Person { }
User user = new User();//先加载父类
4).反射方式创建类的class对象
Class clazz = Class.forName("Person");
获取Class对象的三种方式
1).类的静态属性(该方法最为安全可靠,程序性能更高)
Class clazz = Person.class;
2).对象的getClass()方法(通常应用在:比如你传过来一个 Object 类型的对象,而我不知道你具体是什么类,用这种方法)
Person person = new Person();
Class clazz = person.getClass();
Object obj = new Person();
Class clazz = obj.getClass();
3).Class类的静态方法(用的最多,可能抛异常:ClassNotFoundException)
Class clazz = Class.forName("com.reflect.Person");
常用构造器
Class clazz = Person.class;
//1.获取全部构造器
Constructor[] Constructors = clazz.getConstructors();
//2.获取某一个构造器,需要参数列表
Constructor<Person> constructor = clazz.getConstructor(String.class, int.class);
//3.调用构造器的 newInstance() 方法创建对象
Object obj = constructor.newInstance("zhaojie", 1);
常用本类方法
//1.获取类中的所有方法(包括继承父类的方法),但是获取不到本类私有方法
Method[] methods = clazz.getMethods();
//2.只获取当前类的方法,包括私有方法
Method[] methods = clazz.getDeclaredMethods();
//3.获取某一个方法(没有入参则不写)
method = clazz.getDeclaredMethod("setAge", Integer.class);
System.out.println(method);
// 如果方法用于反射,那么要么int类型( 或者写成 :int.class)写成Integer: public void setAge(Integer age) { }
// invoke第一个参数表示执行哪个对象的方法,剩下的参数是执行方法时需要传入的参数
Object obje = clazz.newInstance();
method .invoke(obje,2);
System.out.println("输出getAge方法:"+method );
//私有方法的执行,必须在调用invoke之前加上一句method.setAccessible(true);
获取父类方法
Class clazz = Class.forName("com.reflect.Student");
//获取父类类名
Class superClazz = clazz.getSuperclass();
获取字段
//获取公用和私有的所有字段,但不能获取父类字段
Class clazz = Person.class;
Field[] fields = clazz.getDeclaredFields();
//获取指定字段
Field field = clazz.getDeclaredField("name");
Person person = new Person("ABC",12);
// 2.1获取指定对象的指定字段的值
Object val = field.get(person);
System.out.println(val);
// 2.2设置指定对象的指定对象Field值
field.set(person, "DEF");
System.out.println(person.getName());
// 2.3如果字段是私有的,不管是读值还是写值,都必须先调用setAccessible(true)方法