JAVA反射机制
何为反射?
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
反射有什么作用?
反射可以在我们运行时,加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields(成员属性)设值、或唤起其methods成员方法。
反射可以程序运行时,改变程序结构或变量类型,比如为一个Integer集合添加String元素
也可以改变或获取成员属性(字段),获取构造方法,获取并调用成员方法,
反射怎么用?
1. 获取字节码对象的三种方法:
获取字节码对象的方式一:
* 1,Object类中的getClass()方法的。
* 想要用这种方式,必须要明确具体的类,并创建对象。
* 缺点:不够简单
public static void getClassObject_1(){
Person p = new Person();
Class clazz = p.getClass();
方式二:
* 2,任何数据类型都具备一个静态的属性.class来获取其对应的Class对象。
* 相对简单,但是还是要明确用到类中的静态成员。
* 缺点:不够扩展。
public static void getClassObject_2() {
Class clazz = Person.class;
方式三:最常用
* 只要通过给定的类的 字符串名称就可以获取该类,更为扩展。
* 可是用Class类中的方法完成。
* 该方法就是forName.
* 这种方式只要有名称即可,可以将名称写在配置文件中,同时给定一个引用名,用forName与引用名关联,到时候对象名有更改,那么只需要修改引用所对应的类名字符串就可以. 更为方便,扩展性更强。
String className = "cn.itcast.bean.Person";(这里要注意:是包名.类名的字符串表现形式,这与导不导包没有关系)
Class clazz = Class.forName(className);
2. 获取构造方法得到对象
关健字:Construtor
获取对象方法.newInstance
1.当只需要获得无参构造成的对象时
String name = "cn.itcast.bean.Person";
//找寻该名称类文件,并加载进内存,并产生Class对象。
Class clazz = Class.forName(name);
//如何产生该类的对象呢?
Object obj = clazz.newInstance();
2.当想获取有参构造的对象.
String name = "cn.itcast.bean.Person";
//找寻该名称类文件,并加载进内存,并产生Class对象。
Class clazz = Class.forName(name);
//获取到了指定的构造函数对象。
Constructor constructor = clazz.getConstructor(String.class,int.class);(这里传构造方法参数类型的字节码对象)
这里可以用可变参数,也就是用一个数组也可实现:
或:Constructor constructor = clazz.getConstructor(new Class[]{String.class,int.class});
//通过该构造器对象的newInstance方法进行对象的初始化。
Object obj = constructor.newInstance("小明",38);(直接传构造方法参数)
或:Object obj = constructor.newInstance(Object[]{"小明",38});(直接传构造方法参数)
Constructor[] constructor = clazz.getConstructors();
这是获取包含所有按由上至下的构造方法的,一个数组
3. 获取和改变成员属性(字段)
这有两种,
一是公共(public )字段:Field field = null;//clazz.getField("age");//只能获取公有的,
二是非公共字段:
Class clazz = Class.forName("cn.itcast.bean.Person");
field = clazz.getDeclaredField("age");//只获取本类,但包含私有。
//对私有字段的访问取消权限检查。暴力访问。
field.setAccessible(true);
Object obj = clazz.newInstance();
field.set(obj, 89);(里面的参数是,对象+想要设制的值)
Object o = field.get(obj);获得改字段的
4. 获取和运行成员方法
Class clazz = Class.forName("cn.itcast.bean.Person");
Method method = clazz.getMethod("paramMethod", String.class,int.class);
参数(方法名字符串表现形式,方法参数1的字节码对象1,方法参数2的字节码对象)
Object obj = clazz.newInstance();
method.invoke(obj, "小强",89);(本类对象,方法参数1,方法参数二)
Method[] methods = clazz.getMethods();//获取的都是公有的方法的数组。
返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法。
Method[] methods = clazz.getDeclaredMethods();//只获取本类中所有方法,包含私有的数组。
返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。
反射什么时候用?
经典的就是xml或者properties里面写上了配置,然后在Java类里面解析xml或properties里面的内容,得到一个字符串,然后用反射,根据这个字符串获得某个类的实例,这样就可以动态配置一些东西,不用每一次都要在代码里面去new或者做其他的事情,以后要改的话直接改配置文件,代码维护起来就很方便了,同时有时候要适应某些需求,Java类里面不一定能直接调用另外的方法,这时候也可以通过反射机制来实现。
总的来说,自己写的很少,具体什么时候要用那要看需求,楼上说得对,无非就是根据一个String来得到你要的实体对象,然后调用它原来的东西。但是如果是要自己写框架的话,那就会用得比较多了。
|