反射
Java的反射(reflection)机制是指在程序的运行状态中
可以构造任意一个类的对象
可以了解任意一个对象所属的类
可以了解任意一个类的成员变量和方法
可以调用任意一个对象的属性和方法
这种动态获取程序信息以及动态调用对象的功能称为Java语言的反射机制。反射被视为动态语言的关键。
Java反射描述的是,在运行状态中:
1、对于任意一个类,都能够知道这个类的所有属性和方法
2、对于任意一个类,都能够调用它的任意一个属性和方法
之所以强调属性、方法,是因为属性、方法是开发者对于一个类最关注的两个部分。实际上通过反射,不仅仅可以获知类的属性、方法,还可以获知类的父类、接口、包等信息
至于反射的原理,不难,Java类加载机制一文中讲到了,一个类在加载的时候,会在内存中生成一个代表这个.class文件的java.lang.Class对象,.classs文件里面就包含了描述这个类的信息的一切内容。至于.class文件,是由Java编译器(注意是Java编译器,指的不仅仅是Javac)编译而来的,是编译原理的领域;.class文件结构,网上很多讲解了,比如类文件结构,这里就不讲了。
一、获取class对象的方式
1. Class.forName("全类名")
将字节码文件加载进内存,返回Class对象
这是一个静态的方法static 多用于配置文件,将类名定义在配置文件中。读取文件,加载类
2. 类名.class:通过类名的属性class获取 多用于参数的传递
3. 对象.getClass():getClass()方法在Object类中定义着。
出现这个问题可能是包名或者类名写错了。
Class cls1 = Class.forName("cn.ww.Person");
Class cls2=Person.class;
Person ps=new Person();
Class cls3 = ps.getClass();
System.out.println(cls2==cls3);
System.out.println(cls1==cls3);
System.out.println(cls1==cls2);
//返回值全都为true
* 结论:
同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个。
二、class对象功能
1、获取功能
1)获取成员变量们
① Field[] getFields() :获取所有public修饰的成员变量
②Field getField(String name) 获取指定名称的 public修饰的成员变量
//获取成员变量以后可以进行操作,已知有一个Person对象 //首先获取Person的Class对象 Class personClass =Person.class; Field fields = personClass.getField("a") //获取成员变量中 public String a 中 的值 Person p = new Person(); Object value=fields.get(p); //结果就会打印a的值
//set 和 get 两个方法
③ Field[] getDeclaredFields() 获取所有的成员变量,不考虑修饰符
④Field getDeclaredField(String name)
Class personClass =Person.class;//获取Person的class对象
Field d = personClass.getDeclaredField("d"); //忽略访问权限修饰符的安全检查 d.setAccessible(true);//暴力反射 Object value =d.get(p);
2)获取构造方法们
方法名和类名相同,本质就是来创建对象的
① Constructor<?>[] getConstructors()
② Constructor<T> getConstructor(类<?>... parameterTypes)
③ Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)
④ Constructor<?>[] getDeclaredConstructors()
Constructor constructor =personClass.getConstructor(String.class , int.class);//返回了一个构造器 Object person = constructor.newInstance("你好",18);//创建对象 Object person = constructor.newInstance();//空参
//如果使用空参构造,可以直接使用class对象里面的方法 Class personClass = Person.class; personClass。newInstance();
3)获取成员方法们
①Method[] getMethods() 只能获取public的
②Method getMethod(String name, 类<?>... parameterTypes)
③Method[] getDeclaredMethods() 不考虑修饰符
④Method getDeclaredMethod(String name, 类<?>... parameterTypes)
Class personClass =Person.class; Method eat2 = personClass.getMethod("eat2",String.class); Person person = new Person(); eat2.invoke(person,"米饭");