反射:
反射是我们 经常用到的一个知识点,那什么是反射呢?
反射就是在程序运行过程中分析类的一种能力 | |
---|---|
在这里我们想一下我们在编写java的时候,先写java源文件——>字节码文件(class文件)——>然后就可以通过 对象.方法调用具体的方法,反射就是吧这个动作的反过来就可以理解为反射。
对象.方法——>字节码文件——>访问里边的其它方法和属性。
那反射能做什么事情呢?
-
分析类(通过类加载器实现的)
加载并初始化一个类
查看类的所有属性和方法 -
查看并使用对象
查看一个对象的所有属性和方法
使用对象的任意属性和方法
下面我们先说第一个重要的知识点
类加载器(classloader)
负责将类的字节码文件(.class文件)加载 到内存中,并生成对应的Class对象(每个类只有一个class对象)。
下面我们通过代码演示什么时候加载类的class对象:
//创建类的实例
Student stu = new Student();
//访问类的静态成员
People.sleep();//静态方法
//调用人的静态方法或成员变量时就会创建 对应的class对象
//初始化类的子类
class User extends Person{}
//这里就会先加载父类的claas对象再加载子类的class对象
//反射方式创建类的class对象
Class class = Class.forName("类的正名");
//正名:包名+类名
通俗点来说就是当你使用一个类的一个成员时类的加载器就会吧对应的class对象加载到内存中。
获取Class对象的三种方式
:
- Object 类的getClass()方法。
Class class = 对象名.getClass();
- 类的静态属性
Class class = 类名.class;
- Classl类的静态方法
Class class = Class.forName("类的正名");
Class类常用方法
Class类提供了很多方法让我们使用,看一下我们常用的方法有哪些;
public static void reflexMethod3() throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
//获取Class对象
Class itemcls = Class.forName("cn.yunhe.beans.Item");
//获取所有公共的构造器
//Constructor[] cons = itemcls.getConstructors();
//获取所有的构造器包括私有的
Constructor[] cons = itemcls.getDeclaredConstructors();
for (int i = 0; i < cons.length; i++) {
//cons[i].getParameterCount()获取构造器中形参的个数
// System.out.println(cons[i] + " " + cons[i].getParameterCount());
if (cons[i].getParameterCount() == 2) {
//要创建带有具体参数的对象
Item item = (Item) cons[i].newInstance("phone",4999);
System.out.println(item);
}
}
}
/**
* 获取方法
* @throws ClassNotFoundException
* @throws SecurityException
* @throws NoSuchMethodException
*/
public static void method() throws ClassNotFoundException, NoSuchMethodException, SecurityException {
Class itemCls = Class.forName("cn.yunhe.beans.Item");
//获取方法 getDeclaredMethods();只获取当前对象的方法
Method[] methods= itemCls.getDeclaredMethods();
//获取方法 getMethods();获取当前对象的全部方法(包括父类中继承的方法)
// Method[] methods= itemCls.getMethods();
for (int i = 0; i < methods.length; i++) {
System.out.println(methods[i]);
//参数一:方法名 参数二: 参数类型
Method method = itemCls.getMethod("setItemNameString", String.class);
System.out.println(method);
}
}
/**
* 获取属性
* @throws ClassNotFoundException
*/
public static void property() throws ClassNotFoundException {
Class itemCls = Class.forName("cn.yunhe.beans.Item");
// 获取属性 getFields() 只能获取当前的对象的属性
// Field[] fils = itemCls.getFields();
// 获取属性 getDeclaredFields() 获取当前对象的全部属性,包括私有的、公共的、默认的、受保护的
Field[] field =itemCls.getDeclaredFields();
for (int i = 0; i < field.length; i++) {
System.out.println(field[i]);
}
}
}
注意点:
1、我们在使用第三方的Jar包的时候,他里面没有Java文件,只有Class文件,我们怎么才能知道class文件里的到底有什么呢,可以用反射机制进行反射,找到里面的方法及属性,怎么让程序才知道我要去反射哪一个Class文件呢,给到一个包名加类名=路径名,那就可以找到这个路径了,就能找到Class文件了,对这个CLass类里面人家提供了有方法,用来获取各种各样类里面的东西,我们首要前提找构造器,因为我们要创建对象