一、反射是什么?
Java反射机制是在运行状态中,对于任何一个类(class文件),都能够知道这个类地所有属性和方法;对于任何一个对象,都能够调用它地任何一个方法和属性;这种动态获取地信息以及动态调用对象方法的功能称为java语言的反射机制。
动态获取类中信息,就是java反射。
可以理解为对类的解剖。
如果想要对指定名称的字节码文件进行加载并获取其中的内容并调用,这时就使用到了java反射技术。
反射的好处:大大的增强了程序的扩展性
二、反射的基本步骤
- 获得Class对象,即获取到指定名称的字节码文件对象。
- 实例化对象,获得类的属性、方法或构造函数。
- 访问属性、调用方法、调用构造函数创建对象。
1.获取Class对象,有三种方式
1:通过每个对象都具备的方法getClass来获取。
Class c2 = stu.getClass()
弊端:必须要创建该类对象,才可以调用getClass方法。*
2:每一个数据类型(基本数据类型和引用数据类型)都有一个静态的属性class。
Class c1 = Student.class
弊端:必须要先明确该类。
上面这两种方式不利于程序的扩展,因为都需要在程序使用具体的类来完成。
3:使用的Class类中的方法,静态的forName方法。指定什么类名,就获取什么类字节码文件对象,这种方式的扩展性最强,只要将类名的字符串传入即可。
Class clazz = Class.forName("com.ds.reflect.Person");
2.创建指定类的对象,有两种方式
-
调用空参数的构造函数:
即使用Class类中的newInstance()方法。Class clazz = Class.forName("com.ds.reflect.Person"); Person instance = (Person) clazz .newInstance();
-
调用带参数的构造函数:
先要获取指定参数的构造器对象,然后通过该构造器对象的newInstance(实际参数) 进行对象的初始化。
弊端:必须要先明确具体的构造函数的参数类型,不便于扩展。Class clazz = Class.forName("com.ds.reflect.Person"); Constructor con = clazz.getConstructor(new Class[]{String.class,int.class}); Person instance = (Person) con.newInstance("name",18);
获取构造函数区别
1.Constructor<?>[] getConstructors() 获取该类中所有的构造方法, 返回的是一个数组
2.Constructor getConstructor(Class<?>… parameterTypes) 接受一个可变参数, 可以根据传入的类型, 来匹配对应的构造方法
3.获取类中的方法,属性
1. 获取方法
a.getMethods() 获取的是该类中所有的公有方法,包含继承和实现的方法
b.getDeclaredMethods() 获取的是该类中的所有方法,包含private方法,但不包含继承的方法。
c.getMethod(“show”, int.class,String.class)获取指定名称的方法
d.getDeclaredMethod(“method”, null)获取private方法
e.getMethod(“function”,null)获取static方法
Class clazz = Class.forName("com.ds.reflect.Person");
Method[] methods = clazz.getMethods();//a
___________________________________________________
methods = clazz.getDeclaredMethods();//b
for(Method method : methods) {
System.out.println(method);
___________________________________________________
Class clazz = Class.forName("com.ds.reflect.Person");
Method method = clazz.getMethod("show", int.class,String.class);//c
Object obj = clazz.newInstance();
method.invoke(obj, 39,"hehehe");//执行一个方法
___________________________________________________
Class clazz = Class.forName("com.ds.reflect.Person");
Method method = clazz.getDeclaredMethod("method", null);//d
method.setAccessible(true);//私有方法权限不够,不能直接访问,非要访问,只能通过此方式。但还是尽量不要访问。
___________________________________________________
Class clazz = Class.forName("com.ds.reflect.Person");
Method method = clazz.getMethod("function",null);//e
method.invoke(null,null);
2.获取属性
Field getField(String name) 只能获取类的public 字段
Field getDeclaredField(String name) 获取一个类的所有字段
Field[] getFields() 只能获得类中public字段,包含父类中的public 字段
Field[] getDeclaredFields() 获得类中所有的字段,包括public字段和private字段,默认字段和受保护字段。但是不能获得父类中所有的字段