Java反射机制
来源:互联网 发布:unity3d 钱币资源 编辑:程序博客网 时间:2024/05/04 08:00
介绍
Java反射机制是很多框架使用的基础.
当程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言。
我们认为java并不是动态语言,但是它却有一个非常突出的动态相关机制,俗称:反射。
反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;
对于任意一个对象,都能够调用它的任意一个方法和属性;
这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
反射机制主要提供了以下功能:
1,在运行时判断任意一个对象所属的类;
2,在运行时构造任意一个类的对象;
3,在运行时判断任意一个类所具有的成员变量和方法;
4,在运行时调用任意一个对象的方法;
5,生成动态代理。
Demo
为了学习,我做了一个测试的demo:
基本框架如下:
public class ReflectionTest { public static void main(String[] args) { test7(); } /****测试方法****/}class F{ public String name; public int id; public F(){ } public F(String name,int id){ this.name=name; this.id=id; }}
F是用来做例子的类,main函数里调一个个测试的demo,这样就只需要建一个文件了。下面是一个一个实验:
Test1:
//第一个实验,了解Class类的概念,Java中"万物皆为class",java.lang包中的位置说明了他的大佬地位 //本实验,将会练习如何动态获得一个对象或者一个类的类名,让你更将深入地了解Class static void test1(){ F f=new F();//定义和初始化一个类对象 Class c1=F.class;//定义一个Class对象,初始化为F.class, //很多博客在这一点上解释为,class是F的一个静态变量,或者说每一个类都有一个隐式的class域 //这似乎挺对,也有助于理解,然而我有点不同意见, //如果class是一个静态变量,那么它的实例也有这个变量,然而实际上,当我输入Class c2=f.class的时候,是会报错的 //因此我认为这句话就是把F.class本身的实体赋予了c1,在Java编译时就加载进去. Class c2=f.getClass();//通过实例对象的getClass方法也可以得到类的实体,值得说明的是这个getClass()是Object类的方法,返回这个对象的类型类,好绕 //有趣吧,由此我们更深地了解“万物皆为class”这句话,Class is a class!! Class c3=null; try { c3=Class.forName("F");//第三种获取类型类的方式Class.forClass("XXXX") } catch (ClassNotFoundException e) { e.printStackTrace(); } System.out.println(c1); System.out.println(c2); System.out.println(c3); System.out.println(c1==c2); System.out.println(c2==c3);//从这里看出绝对地址相同,指向同一个东西 }
Test2
//通过类型类来初始化实例 static void test2(){ Class c=F.class; F f=null; try { f=(F)c.newInstance();//newInstance是Class类的方法,返回一个新的泛型对象,强制转型为F对象 //这句话如果改为f=f.getClass().newInstance()不需要转型 } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } System.out.println(f); System.out.println(f.getClass()); System.out.println(f.getClass().getName()); }
Test3
//为了加深实验二印象,做了实验三,发现重新初始化前后的绝对地址发生变化,确定确实初始化了一个新实例,改变了f的引用 static void test3(){ F f=new F(); System.out.println(f); try { f=f.getClass().newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } System.out.println(f); }
Test4
//实验四, static void test4(){ Class c1=String.class; Object c2=void.class; Class c3=void.class; Class c4=int.class; System.out.println(c1.getName());//通过Class的getName方法可以获得类的名称, System.out.println(c1.getSimpleName());//getSimpleName获取不含包完整路径的类名 System.out.println(c2.getClass().getName());//如果是对象需要先获得为对应的类型类 System.out.println(c3.getName());//我们会发现void也有一个类型 System.out.println(c4.getName());//int是基本数据类型,没有所属的包,void也是如此 }
Test5
//实验五,动态获取类型方法 public static void test5(){ ReflectionTest rt=new ReflectionTest(); Method[] ms=rt.getClass().getMethods();//Class的getMethods()方法,返回类型的所有共有方法 //Method[] ms=rt.getClass().getDeclaredMethods();//把上一行替换成这个看看输出的方法有什么区别 for(Method m:ms){ System.out.println(m); System.out.println(m.getName());//method.getName()获取方法名 Class returnType=m.getReturnType();//method.getReturnType()获取返回参数类型 System.out.println(returnType); System.out.println(returnType.getName());//获取返回参数类型的名字 Class[] parameters=m.getParameterTypes();//method.getParameters获取方法传入参数的类型 for(Class p:parameters){ System.out.print(p+","); } System.out.println(); } } //实验五的辅助函数, //这个函数的返回类型输出如下:int,class [I,class [D,class [Ljava.lang.String;,class [Lcom.way.reflection.F;, //这是描述标识字符,就是将对象转换成的字节码 public static int test5add(int a,int[] b,double[] c,String[] d,F[] e){ return 0; }
描述标识字符就是将.java文件编译成.class文件后对象转换成的字节码。表示字符所代表的含义如下:
Test6
//实验六,获取成员变量 static void test6(){ F ff=new F("test",1); Class c=F.class; Field[] fields=c.getFields(); for(Field f:fields){ try { System.out.println(f.get(ff));//field.get(Object obj)获取对象的对应成员变量对象(Object) } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } System.out.println(f.getType());//field.获取类型成元变量的类型类 } }
Test7
//实验七 static void test7(){ Class c=F.class; Constructor[] cs=c.getConstructors(); for(Constructor constructor:cs){ System.out.println(constructor.getName()); Class[] parameters=constructor.getParameterTypes(); if(parameters.length==0){ System.out.println("No parameter constructor"); }else{ for(Class parameter:parameters){ System.out.println(parameter.getName()); } } } }
Test8
反射可以拿到一个类所有的方法和属性,包括父类和接口。很多时候我们不想获取父类和接口的东西,只想要本类中声明的属性和方法。于是就有了Class.getDeclaredXXXX()的方法,在前面试验过的各种get方法中间插入Declared,就可以获取本类的方法,实验8就是为了说明这件事。
为了说明问题,需要对F类稍作改动,就是需要F继承任意一个类,或者实现任意的接口,在这里我让他继承了Thread类,其他都不变。
class F extends Thread{
//实验8,测试Declared的get方法 static void test8(){ Class c=null; try { c=Class.forName("F"); } catch (ClassNotFoundException e) { e.printStackTrace(); } System.out.println(c.getMethods().length); System.out.println(c.getDeclaredMethods().length); }
输出结果
500
可以得知,Thread有50个公共方法被F类继承了。类似的Declared的get方法概不赘述了。
总结
**获取类类型:**Class c=F.class;Class c=Class.forName("F");Class c=f.getClass(); //Object.getClass()**获取类实例:**F f=new F(); //非反射做法F f=c.newInstance(); //Class.newInstance()**获取类名称:**String fullName=c.getName();String simpleName=c.getSimpleName();**获取类方法:**Method method=c.getMethod(String name,Class<?>... parameterTypes); //java.lang.reflect.MethodMethod[] methods=c.getMethods(); //java.lang.reflect.Method[]Method[] methods=c.getDeclaredMethods();method.getName(); //Stringmethod.getParameterTypes(); //Class[]method.getParameterCount(); //intmethod.getReturnType(); //Class**获取类属性:**Field field=c.getField(String name); //java.lang.reflect.FieldField[] field=c.getFields(); field.getName(); //Stringfield.getType(); //Classfield.get(obj); //Object (the field object of obj)**获取构造器:**Constructor constructor=c.getConstructor(Class<?>... parameterTypes); //java.lang.reflect.constructorConstructor[] constructors=c.getConstructors(); constructor.getName() constructor.getParameterTypes() //Class[]**Declared方法**getDeclaredXXX(); //获取本类的属性,方法构造器,等等
以上的方法只是一部分,详细可以看源码。
参考:
http://www.jianshu.com/p/6277c1f9f48d
http://www.jianshu.com/p/b560b30726d4
这位博主文章写得挺好
- 【反射】JAVA反射机制
- 【Java】JAVA反射机制
- Java 反射机制[Field反射]
- Java 反射机制[Method反射]
- Java反射机制笔记-反射机制
- java的反射机制
- Java的反射机制
- java反射机制详解!
- Java反射机制
- Java的反射机制
- java 反射机制--侯捷
- java反射机制
- java反射机制
- [候捷]Java反射机制
- java 反射机制
- java 反射机制初探
- 关于Java反射机制
- java反射机制
- Web程序的调试与排错
- Vue2.0 Transition的常见用法
- Atitit vue.js 把ajax数据 绑定到form表单
- 剑指Offer面试题11数值的整数次方
- UVM的config机制(五)
- Java反射机制
- SQLYog快捷键大全
- 72字节的串和144字节的串有什么毛关系?------原来是buf2hex
- 进制转换
- VC利用串口完成上下位机的通讯
- 1.9猜数游戏,随机生成一个整数(0-100),用户输入他所猜的数,程序回答大了或者小了,用户再输入他所猜的数,直至猜对了为止
- MFC:“Debug Assertion Failed!” ——自动生成的单文档程序项目编译运行就有错误
- ubuntu 安装本地版storm并运行WordCount
- Android实战——Glide的使用,加载图片只要一句话