JAVA中的反射机制
2016-05-25 17:53
363 查看
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
主要是指程序可以访问,检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。
反射是java中一种强大的工具,能够使我们很方便的创建灵活的代码,这些代码可以再运行时装配,无需在组件之间进行源代码链接。但是反射使用不当会成本很高!
看概念很晕的,继续往下看。
在运行时判断任意一个对象所属的类
在运行时构造任意一个类的对象
在运行时判断任意一个类所具有的成员变量和方法
在运行时调用任意一个对象的方法
在这里先看一下sun为我们提供了那些反射机制中的类:
java.lang.Class;
java.lang.reflect.Constructor; java.lang.reflect.Field;
java.lang.reflect.Method;
java.lang.reflect.Modifier;
类十分特殊。它和一般类一样继承自Object,其实体用以表达Java程序运行时的classes和interfaces,也用来表达enum、array、primitive Java types(boolean, byte, char, short, int, long, float, double)以及关键词void。当一个class被加载,或当加载器(class
loader)的defineClass()被JVM调用,JVM 便自动产生一个Class 对象。如果您想借由“修改Java标准库源码”来观察Class 对象的实际生成时机(例如在Class的constructor内添加一个println()),这样是行不通的!因为Class并没有public constructor。
获得你想操作类的Class对象
通过第一步获得的Class对象去取得操作类的方法或是属性名
操作第二步取得的方法或是属性
Java运行的时候,某个类无论生成多少个对象,他们都会对应同一个Class对象,它表示正在运行程序中的类和接口。如何取得操作类的Class对象,常用的有三种方式:
调用Class的静态方法forName,如上例;
使用类的.class语法,如:Class<?> cls = String.class;
调用对象的getClass方法,如:String str = "abc";Class<?> cls = str .getClass();
首先我们写一个Employee类
1,反射机制获取类有三种方法,我们来获取Employee的Class类
2,创建对象:获取类以后我们来创建它的对象,利用newInstance:
注意,若获取内部类构造方法时,需要将其外部类的类对象作为参数传进去
Constructor constructor = c.getDeclaredConstructor(new Class[] {
Out.class });
同样实例化内部类时,也需要将外部类对象作为参数传进去
obj = constructor.newInstance(new Out());
3,获取属性:分为所有的属性和指定的属性:
4,获取方法
先看一下反射的概念:
主要是指程序可以访问,检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。反射是java中一种强大的工具,能够使我们很方便的创建灵活的代码,这些代码可以再运行时装配,无需在组件之间进行源代码链接。但是反射使用不当会成本很高!
看概念很晕的,继续往下看。
反射机制的作用:
在运行时判断任意一个对象所属的类
在运行时构造任意一个类的对象
在运行时判断任意一个类所具有的成员变量和方法
在运行时调用任意一个对象的方法
在这里先看一下sun为我们提供了那些反射机制中的类:
java.lang.Class;
java.lang.reflect.Constructor; java.lang.reflect.Field;
java.lang.reflect.Method;
java.lang.reflect.Modifier;
class 类
众所周知Java有个Object 类,是所有Java 类的继承根源,其内声明了数个应该在所有Java 类中被改写的方法:hashCode()、equals()、clone()、toString()、getClass()等。其中getClass()返回一个Class 对象。Class类十分特殊。它和一般类一样继承自Object,其实体用以表达Java程序运行时的classes和interfaces,也用来表达enum、array、primitive Java types(boolean, byte, char, short, int, long, float, double)以及关键词void。当一个class被加载,或当加载器(class
loader)的defineClass()被JVM调用,JVM 便自动产生一个Class 对象。如果您想借由“修改Java标准库源码”来观察Class 对象的实际生成时机(例如在Class的constructor内添加一个println()),这样是行不通的!因为Class并没有public constructor。
具体实现
使用java的反射机制,一般需要遵循三步:获得你想操作类的Class对象
通过第一步获得的Class对象去取得操作类的方法或是属性名
操作第二步取得的方法或是属性
Java运行的时候,某个类无论生成多少个对象,他们都会对应同一个Class对象,它表示正在运行程序中的类和接口。如何取得操作类的Class对象,常用的有三种方式:
调用Class的静态方法forName,如上例;
使用类的.class语法,如:Class<?> cls = String.class;
调用对象的getClass方法,如:String str = "abc";Class<?> cls = str .getClass();
首先我们写一个Employee类
public class Employee { public Employee(){ name = "nick"; age = 25; } String name=""; int age=0; public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
1,反射机制获取类有三种方法,我们来获取Employee的Class类
//第一种方式: Class c1 = Class.forName("package.xxx.Employee"); //完整的路径名 //第二种方式: //java中每个类型都有class 属性. Class c2 = Employee.class; //第三种方式: //java语言中任何一个java对象都有getClass 方法 Employee e = new Employee(); Class c3 = e.getClass(); //c3是运行时类 (e的运行时类是Employee)注意 Employee若是内部类,这类名前为$号,而不是“.”
2,创建对象:获取类以后我们来创建它的对象,利用newInstance:
Class c =Class.forName("com.jd.wxsq.jzcircle.bean.Employee"); //创建此Class 对象所表示的类的一个新实例 Object o = c.newInstance(); //调用了Employee的无参数构造方法.
注意,若获取内部类构造方法时,需要将其外部类的类对象作为参数传进去
Constructor constructor = c.getDeclaredConstructor(new Class[] {
Out.class });
同样实例化内部类时,也需要将外部类对象作为参数传进去
obj = constructor.newInstance(new Out());
3,获取属性:分为所有的属性和指定的属性:
//获取所有的属性? Field[] fs = c.getDeclaredFields(); //定义可变长的字符串,用来存储属性 StringBuffer sb = new StringBuffer(); //通过追加的方法,将每个属性拼接到此字符串中 //最外边的public定义 sb.append(Modifier.toString(c.getModifiers()) + " class " + c.getSimpleName() +"{\n"); //里边的每一个属性 for(Field field:fs){ sb.append("\t");//空格 sb.append(Modifier.toString(field.getModifiers())+" ");//获得属性的修饰符,例如public,static等等 sb.append(field.getType().getSimpleName() + " ");//属性的类型的名字 sb.append(field.getName()+";\n");//属性的名字+回车 } sb.append("}");由打印信息我们可以看到能够获取到Employee的所以成员。
//获取特定的“name"属性 Field f = c.getDeclaredField("name"); //使用反射机制可以打破封装性,导致了java对象的属性不安全,设置可访问 f.setAccessible(true); //给o对象的name属性赋值 f.set(o,"Join");通过上面方法我们可以获取指定的属性,并改变它的值。
4,获取方法
//获取特定的setAge方法,Integer.TYPE为其对应的形参数类型 Method method = c.getDeclaredMethod("setAge",Integer.TYPE); //调用特定的setAge方法,若为静态方法,则invoke的第一个参数为null method.invoke(o,100);
相关文章推荐
- JAVA 笔记(三) 从源码深入浅出集合框架
- Struts2_类型转换错误消息的显示和定制
- RxJava介绍
- java 上传文件到七牛云存储的demo
- 【第九章】 Spring的事务 之 9.1 数据库事务概述 ——跟我学spring3
- Java面向对象经典总结
- Java程序的初始化顺序
- X的N次方 朴素分治法-Java
- java多线程调用run和不调用run的区别
- 如何用HotSwapAgent和DCEVM让java开发像js开发一样高效(JRebel的替代方案)
- Java内存泄漏--程序和内存的关系
- ROC曲线判别线性回归,java实现。
- JAVA多线程(五)用lock、synchronized、阻塞队列三种方法实现生产者消费者模式
- 大力推荐的超牛GitHub top 100的Java开源库
- 关于this关键字的用法
- javaIOzongji
- JAVA 三大GC(java6.0)
- Spring下jdbcTemplate增删改查总结
- java设计模式-工厂方法模式
- 二分法查找-Java