Java的反射机制是指在运行中,对于任意一个类(class文件),都能够知道这个类的属性和方法。对于任意一个对象,都能够调用它的任意一个方法和属性,这种动态获取信息,以及动态调用对象的方法的功能称为反射机制。
即动态获取类中的信息,就是Java的反射机制。
对象.属性或者对象.方法就是静态获取类中的信息。
-
字节码文件
字节码文件在内存中也是以对象的形式存在的,它的类型就是class
class:是一个类的描述符,用来描述类的特征
-
获取字节码文件的第一种方式 利用Object类中的getClass()方法,想用这种方式,必须要明确具体的类,创建对象
Person p = new Person(); Class clazz = p.getClass(); // p对应的字节码文件
-
获取字节码文件的方式二 任何数据类型都具备一个静态属性---class,该属性可以获取对应的.class对象。这种方式相对简单,但是还需要明确到类中的静态成员,扩展性不是很强。
Class clazz = Person.class;
-
获取字节码文件的方式三 只要通过给定类的字符串名称,就可以获取该类对应的字节码文件对象,这种方式更为扩展。可以利用Class类中的forName()方法完成。这种方式只需要名称即可,更为方便,更为扩展
Class clazz = Class.forName("reflect.Person"); // 类名全称,包括包名
利用Class类中的forName()方法获得字节码文件对象
// 获取字节码文件
String className = "reflect.Person";
Class clazz = Class.forName(className);直接利用Class类中的newInstance()方法
// 如何产生该类的对象
Object obj = clazz.newInstance(); // 直接可以使用无参构造器创建对象,返回Object,这儿的obj就是一个Person对象利用Class类中getConstrunctor()获得一个有参构造器对象,然后利用该构造器创建对象
Constructor constructor = clazz.getConstructor(int.class, String.class); // 返回的是一个构造器对象
// 利用该构造器创建对象
Object obj = constructor.newInstance(23, "旺财");// getField获取的是公有的字段
Field field = clazz.getField("age");
// 获取该字节码文件对象中所有权限修饰的字段
Field field = clazz.getDeclaredField("age");获取到字段之后,还需要借助对象才可以访问字段的值。由于字段的访问权限问题,所有有以下几种情况
// 1. 访问公有字段
Object obj = clazz.newInstance();
Object o = field.get(obj); // 获取obj对象中的field字段,返回一个Object
// 2. 访问私有字段
field.setAccessible(true); // 对私有的字段的访问权限取消检查(暴力访问),不建议使用
Object obj = clazz.newInstance();
Object o = field.get(obj); // 获取obj对象中的field字段,返回一个Object
// 设置值
field.set(obj, value); // value是要设置的值-
获取所有的公共(public)方法,包括父类中的方法也会获取
Method[] methods = clazz.getMethods();
-
只获取该类中的自定义的所有的方法(包括私有的),不包括父类的
Method[] methods = clazz.getDeclaredMethods();
-
获取一个无参的方法(获取show()方法),无法获得私有的方法
Method method = clazz.getMethod("show", null); // null表示该方法(show())是无参方法 // 运行方法,需要依赖于对象 Object obj = clazz.newInstance(); method.invoke(obj, null);
-
获取一个有参的方法(获取paramMethod(String name, int age)方法),无法获得私有的方法
Method method = clazz.getMethod("paramMethod", String.class, int.class); Object obj = clazz.newInstance(); method.invoke(obj, "旺财", 52);