说到反射,相信有过编程经验的人都不会陌生。反射机制让Java变得更加的灵活。反射机制在Java的众多特性中是非常重要的一个。下面就让我们一点一点了解它是怎么一回事。
什么是反射
在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
反射有什么用
1,在运行时判断任意一个对象所属的类;
2,在运行时构造任意一个类的对象;
3,在运行时判断任意一个类所具有的成员变量和方法;
4,在运行时调用任意一个对象的方法;
5,生成动态代理。
反射的API
学习一门语言,一种比较好的方式就是看它的API文档,因为它的API是最权威的,最准确的。下面我们一起看看JDK的API对于反射是如何描述的吧!
与反射有关的所有接口以及类都在java.lang.reflect包里。
接口
接口摘要
AnnotatedElement
表示目前正在此 VM 中运行的程序的一个已注释元素。
GenericArrayType
GenericArrayType 表示一种数组类型,其组件类型为参数化类型或类型变量。
GenericDeclaration
声明类型变量的所有实体的公共接口。
InvocationHandler
InvocationHandler 是代理实例的调用处理程序 实现的接口。
Member
成员是一种接口,反映有关单个成员(字段或方法)或构造方法的标识信息。
ParameterizedType
ParameterizedType 表示参数化类型,如 Collection<String>。
Type
Type 是 Java 编程语言中所有类型的公共高级接口。
TypeVariable<D extends GenericDeclaration>
TypeVariable 是各种类型变量的公共高级接口。
WildcardType
WildcardType 表示一个通配符类型表达式,如 ?、? extends Number 或 ? super Integer。
类
类摘要
AccessibleObject
AccessibleObject 类是 Field、Method 和 Constructor 对象的基类。
Array
Array 类提供了动态创建和访问 Java 数组的方法。
Constructor<T>
Constructor 提供关于类的单个构造方法的信息以及对它的访问权限。
Field
Field 提供有关类或接口的单个字段的信息,以及对它的动态访问权限。
Method
Method 提供关于类或接口上单独某个方法(以及如何访问该方法)的信息。
Modifier
Modifier 类提供了 static 方法和常量,对类和成员访问修饰符进行解码。
Proxy
Proxy 提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类。
ReflectPermission
反射操作的 Permission 类。
下面给大家写了一个小实例:
[java] view plaincopy在CODE上查看代码片派生到我的代码片
package reflection;
public class UserInfo {
private Integer id;
private String userName;
private String password;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString(){
return this.getClass().getName();
}
}
[java] view plaincopy在CODE上查看代码片派生到我的代码片
package reflection;
public class GetClass {
public boolean ClassCheck(){
try {
System.out.println("第一种,通过类本身获得对象");
Class UserClass = this.getClass();
System.out.println("第一种方式成功!类名:"+UserClass.toString()+"\n");
System.out.println("第二种,通过子类实例获取父类");
UserInfo ui = new UserInfo();
UserClass = ui.getClass();
Class SubUserClass = UserClass.getSuperclass();
System.out.println("第二种方式成功!类名:"+SubUserClass.toString()+"\n");
System.out.println("第三种,通过类名加.class获得对象");
Class ForClass = reflection.UserInfo.class;
System.out.println("第三种方式成功!类名:"+ForClass.toString()+"\n");
System.out.println("第四种,通过类名的字符串获得对象");
Class ForName = Class.forName("reflection.UserInfo");
System.out.println("第四种方式成功!类名:"+ForName.toString()+"\n");
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
@Override
public String toString(){
return this.getClass().getName();
}
public static void main(String[] args) {
GetClass gc = new GetClass();
gc.ClassCheck();
if (gc.ClassCheck()) {
System.out.println("所有反射全部成功!");
}
else {
System.out.println("反射有问题,请检查!");
}
}
}
向大家介绍了什么是Java的反射机制,以及Java的反射机制有什么用。上一篇比较偏重理论,理论的东西给人讲出来总感觉虚无缥缈,还是结合一些实例比较形象具体。那么今天就结合更多的实例具体说说。
实例一:获得完整的类名
[java] view plaincopy在CODE上查看代码片派生到我的代码片
package reflection.getclassname;
//获得完整的类名
public class GetClassName {
public String getNameByClass() {
String name = "";
System.out.println("通过类本身获得对象");
Class UserClass = this.getClass();
System.out.println("获得对象成功!\n");
System.out.println("通过类对象获得类名");
name = UserClass.getName();
System.out.println("获得类名成功!");
return name;
}
public static void main(String[] args) {
GetClassName gcn = new GetClassName();
System.out.println("类名为:"+gcn.getNameByClass());
}
}
运行结果:
通过类本身获得对象
获得对象成功!
通过类对象获得类名
获得类名成功!
类名为:reflection.getclassname.GetClass Name
实例二:获得类的属性
[java] view plaincopy在CODE上查看代码片派生到我的代码片
package reflection.getfields;
import java.lang.reflect.Field;
//获得类的属性
public class GetFields {
public static void getFieldNames(String className) {
try {
//获得类名
Class c = Class.forName(className);
//获得所有属性
Field[] fds = c.getFields();
for (int i=0; i<fds.length; i++)
{
String fn = fds[i].getName();
Class tc = fds[i].getType();
String ft = tc.getName();
System.out.println("该属性的名字为:"+fn+",该属性的类型为:"+ft);
}
}catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
GetFields.getFieldNames("reflection.getfields.FieldInfo");
}
}
运行结果:
该属性的名字为:id,该属性的类型为:java.lang.String
该属性的名字为:username,该属性的类型为:java.lang.String
实例三:获得类实现的接口
[java] view plaincopy在CODE上查看代码片派生到我的代码片
package reflection.getinterfaces;
//获得类实现的接口
public class GetInterfaces {
public static void getInterfaces(String className) {
try {
//取得类
Class cl = Class.forName(className);
Class[] ifs = cl.getInterfaces();
for (int i = 0; i<ifs.length;i++)
{
String IName = ifs[i].getName();
System.out.println("该类实现的接口名字为:"+IName);
}
}catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
GetInterfaces.getInterfaces("reflection.getinterfaces.Student");
}
}
运行结果:
该类实现的接口名字为:reflection.getinterfaces.Person
实例四:获得类及其属性的修饰符
[java] view plaincopy在CODE上查看代码片派生到我的代码片
package reflection.getmodifiers;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import reflection.UserInfo;
//获得类及其属性的修饰符
public class GetModifiers {
private String username = "liu shui jing";
float f = Float.parseFloat("1.000");
public static final int i = 37;
//获得类的修饰符
public static String useModifiers(UserInfo ui) {
Class uiClass = ui.getClass();
int m = uiClass.getModifiers();
return Modifier.toString(m);
}
//获得本类属性的修饰符
public void checkThisClassModifiers() {
Class tc = this.getClass();
Field fl[] = tc.getDeclaredFields();
for(int i=0;i<fl.length;i++)
{
System.out.println("第"+(i+1)+"个属性的修饰符为:"+Modifier.toString(fl[i].getModifiers()));
}
}
public static void main(String[] args) {
//获得类的修饰符
UserInfo ui =new UserInfo();
System.out.println("获得这个类的修饰符:"+GetModifiers.useModifiers(ui)+"\n");
//获得本类属性的修饰符
GetModifiers gm = new GetModifiers();
gm.checkThisClassModifiers();
}
}
运行结果:
获得这个类的修饰符:public
第1个属性的修饰符为:private
第2个属性的修饰符为:
第3个属性的修饰符为:public static final
实例五:获得类的构造函数
[java] view plaincopy在CODE上查看代码片派生到我的代码片
package reflection.getconstructor;
import java.lang.reflect.Constructor;
//获得类的构造函数
public class GetConstructor {
//构造函数一
GetConstructor(int a) {
}
//构造函数二
GetConstructor(int a, String b) {
}
public static void getConstructorInfo(String className) {
try {
//获得类的对象
Class cl =Class.forName(className);
System.out.println("获得类"+className+"所有的构造函数");
Constructor ctorlist[] = cl.getDeclaredConstructors();
System.out.println("遍历构造函数\n");
for(int i =0 ; i<ctorlist.length; i++)
{
Constructor con = ctorlist[i];
System.out.println("这个构造函数的名字为:"+con.getName());
System.out.println("通过构造函数获得这个类的名字为:"+con.getDeclaringClass());
Class cp[] = con.getParameterTypes();
for (int j=0; j<cp.length; j++)
{
System.out.println("参数 "+j+" 为 "+cp[j]+"\n");
}
}
}catch (Exception e) {
System.err.println(e);
}
}
public static void main(String[] args) {
GetConstructor.getConstructorInfo("reflection.getconstructor.GetConstructor");
}
}
运行结果:
获得类reflection.getconstructor.GetConstructor所有的构造函数
遍历构造函数
这个构造函数的名字为:reflection.getconstructor.GetConstructor
通过构造函数获得这个类的名字为:class reflection.getconstructor.GetConstructor
参数 0 为 int
这个构造函数的名字为:reflection.getconstructor.GetConstructor
通过构造函数获得这个类的名字为:class reflection.getconstructor.GetConstructor
参数 0 为 int
参数 1 为 class java.lang.String
实例六:获得父类
[java] view plaincopy在CODE上查看代码片派生到我的代码片
package reflection.getparentclass;
//获得父类
public class GetParentClass {
public static String getParentClass(UserInfoMore uim) {
//获得父类
Class uimc = uim.getClass().getSuperclass();
System.out.println("获得父类的名字为:"+uimc.getName());
return uimc.getName();
}
public static void searchParentClass() {
}
public static void main(String[] args) {
UserInfoMore uim = new UserInfoMore();
System.out.println("成功获得UserInfoMore的父类:"+GetParentClass.getParentClass(uim));
}
}
运行结果:
获得父类的名字为:reflection.UserInfo
成功获得UserInfoMore的父类:reflection.UserInfo
实例七:获得类的方法
[java] view plaincopy在CODE上查看代码片派生到我的代码片
package reflection.getmethod;
import java.lang.reflect.Method;
//获得类的方法
public class GetMethod {
public static void getMethods(String className) {
try {
System.out.println("开始遍历类"+className+".class");
//获得类名
Class cls = Class.forName(className);
//利用方法获得所有该类的方法
System.out.println("利用类的getDeclaredMethods获得类的所有方法");
Method ml[] =cls.getDeclaredMethods();
System.out.println("遍历获得的方法数组\n");
for (int i = 0 ;i<ml.length;i++)
{
System.out.println("开始遍历第"+(i+1)+"个方法");
Method m = ml[i];
System.out.println("开始获取方法的变量类型");
Class ptype[] = m.getParameterTypes();
for (int j=0; j<ptype.length; j++)
{
System.out.println("方法参数"+j+"类型为"+ptype[j]);
}
Class gEx[] = m.getExceptionTypes();
for (int j=0 ; j<gEx.length; j++)
{
System.out.println("异常"+j+"为"+ gEx[j]);
}
System.out.println("该方法的返回值类型为:"+m.getReturnType()+"\n");
}
}catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
GetMethod.getMethods("reflection.UserInfo");
}
}
运行结果:
开始遍历类reflection.UserInfo.class
利用类的getDeclaredMethods获得类的所有方法
遍历获得的方法数组
开始遍历第1个方法
开始获取方法的变量类型
该方法的返回值类型为:class java.lang.String
开始遍历第2个方法
开始获取方法的变量类型
该方法的返回值类型为:class java.lang.Integer
开始遍历第3个方法
开始获取方法的变量类型
方法参数0类型为class java.lang.String
该方法的返回值类型为:void
开始遍历第4个方法
开始获取方法的变量类型
该方法的返回值类型为:class java.lang.String
开始遍历第5个方法
开始获取方法的变量类型
方法参数0类型为class java.lang.Integer
该方法的返回值类型为:void
开始遍历第6个方法
开始获取方法的变量类型
该方法的返回值类型为:class java.lang.String
开始遍历第7个方法
开始获取方法的变量类型
方法参数0类型为class java.lang.String
该方法的返回值类型为:void
转载于:https://my.oschina.net/u/2274056/blog/371629