一般情况下,我们使用某个类时必定知道它是什么类,是用来做什么的,并且能够获得此类的引用。于是我们直接对这个类进行实例化,之后使用这个类对象进行操作。
反射则是一开始并不知道我要初始化的类对象是什么,自然也无法使用 new关键字来创建对象了。这时候,我们使用 JDK提供的反射 API进行反射调用。反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;并且能改变它的属性。是Java被视为动态语言的关键。
反射的作用:
在运行时 构造 任意一个类的对象
在运行时 获取或者修改 任意一个类所具有的成员变量和方法
在运行时 调用 任意一个对象的方法(属性)
Class:
反射始于Class,Class是一个类,封装了当前对象所对应的类的信息。一个类中有属性,方法,构造器等,比如说有一个Person类,一个Order类,一个Book类,这些都是不同的类,现在需要一个类,用来描述类,这就是Class,它应该有类名,属性,方法,构造器等。Class是用来描述类的类。
Class类是一个对象照镜子的结果,对象可以看到自己有哪些属性,方法,构造器,实现了哪些接口等等。对于每个类而言,JRE都为其保留一个不变的 Class类型的对象。一个 Class对象包含了特定某个类的有关信息。对象只能由系统建立对象,一个类(而不是一个对象)在 JVM中只会有一个Class实例。
获得 Class对象:
1、 通过类名获取 类名.class
2、 通过对象获取 对象名.getClass()
3、 通过全类名获取 Class.forName(全类名)、classLoader.loadClass(全类名)
创建实例:
1、使用Class对象的newInstance() 方法来创建对象
Class<?> c = String.class;
Object str = c.newInstance();
2、先通过Class对象获取指定的Constructor对象,再调用Constructor对象的newInstance()方法来创建实例。这种方法可以用指定的构造器构造类的实例
//获取String所对应的Class对象
Class<?> c = String.class;
//获取String类带一个String参数的构造器
Constructor constructor = c.getConstructor(String.class);
//根据构造器创建实例
Object obj = constructor.newInstance("23333");
System.out.println(obj);
获取构造器信息:
Constructor getConstructor(Class[] params)--获得使用特殊的参数类型的public构造函数(包括父类)
Constructor[] getConstructors()--获得类的所有公共构造函数
Constructor getDeclaredConstructor(Class[] params)--获得使用特定参数类型的构造函数(包括私有)
Constructor[] getDeclaredConstructors()--获得类的所有构造函数(与接入级别无关)
获取类的成员变量(字段)信息:
Field getField(String name)--获得命名的公共字段
Field[] getFields()--获得类的所有公共字段
Field getDeclaredField(String name)--获得类声明的命名的字段
Field[] getDeclaredFields()--获得类声明的所有字段
调用方法:
Method getMethod(String name, Class[] params)--使用特定的参数类型,获得命名的公共方法
Method[] getMethods()--获得类的所有公共方法
Method getDeclaredMethod(String name, Class[] params)--使用特写的参数类型,获得类声明的命名的方法
Method[] getDeclaredMethods()--获得类声明的所有方法
方法的执行:
当我们从类中获取了一个方法后,我们就可以用 invoke() 方法来调用这个方法。
利用反射创建数组:
数组在Java里是比较特殊的一种类型,它可以赋值给一个Object Reference其中的Array类为java.lang.reflect.Array类。我们通过Array.newInstance()创建数组对象。