黑马程序员——反射Reflection
2015-08-25 12:28
363 查看
——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-
Java的Reflection(反射)是被市委动态语言的关键,反射机制允许在执行期,借助于Reflection的API取得任何类内部信息,并能直接操作任意对象的内部属性及方法。
Java反射机制提供的功能
在运行时判断任意一个对象所属的类
在运行时构造任意一个类的对象
在运行时判断任意一个类所具有的成员变量和方法
在运行时判断任意一个对象的成员变量和方法
生成动态代理
java.lang.Class:是反射的源头。
* 我们创建了一个类,通过编译(javac.exe),生成对应的.class文件。之后我们使用java.exe加载(JVM的类加载器完成的)
* 此.class文件,此.class文件加载到内存以后,就是一个运行时类,存在在缓存区。那么这个运行时类本身就是一个Class的实例!
1.每一个运行时类只加载一次!
2.有了Class的实例以后,我们才可以进行如下的操作:
1)*创建对应的运行时类的对象
2)获取对应的运行时类的完整结构(属性、方法、构造器、内部类、父类、所在的包、异常、注解、…)
3)*调用对应的运行时类的指定的结构(属性、方法、构造器)
4)反射的应用:动态代理
获取Class实例的方法
1、调用运行时类本身的.class属性
2、通过运行时类的对象获取
3、通过Class的静态方法
4、通过类的加载器
在获取Class的实例后可用通过,newInstance()方法,获取对象实例。
创建对应的运行时类的对象,使用newInstance();要想创建成功要求:
1、对应的运行时类要有空参的构造器,实际上就是调用了运行时类的空参数的构造器
2、构造器的权限修饰付的权限要足够。
所以在创建类时,尽量保留一个空参的构造器。
通过反射调用类的完整结构
1、getFields();只能获取运行时类中声明为Public的属性,包括类中的Public的属性。
2、getDeclaredFields:获取运行时类声明的所有属性,只能获取运行类本身属性,不能获取父类。
field的常见方法
代码:
获取运行时类的方法
1、getMethod();获取运行时类及其弗雷中所有的声明为public的方法。
2、getDelecaredMethods();获取运行时类本身声明的方法
还可以获取权限修饰丰富,返回值类型,方法名,星灿列表,异常等
代码:
获取构造器
反射的应用——动态代理
Proxy :专门完成代理的操作类,是所有动态代理类的父类。通过此类为一个或多个接口动态地生成实现类。
提供用于创建动态代理类和动态代理对象的静态方法
static Class
——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-
Java的Reflection(反射)是被市委动态语言的关键,反射机制允许在执行期,借助于Reflection的API取得任何类内部信息,并能直接操作任意对象的内部属性及方法。
Java反射机制提供的功能
在运行时判断任意一个对象所属的类
在运行时构造任意一个类的对象
在运行时判断任意一个类所具有的成员变量和方法
在运行时判断任意一个对象的成员变量和方法
生成动态代理
java.lang.Class:是反射的源头。
* 我们创建了一个类,通过编译(javac.exe),生成对应的.class文件。之后我们使用java.exe加载(JVM的类加载器完成的)
* 此.class文件,此.class文件加载到内存以后,就是一个运行时类,存在在缓存区。那么这个运行时类本身就是一个Class的实例!
1.每一个运行时类只加载一次!
2.有了Class的实例以后,我们才可以进行如下的操作:
1)*创建对应的运行时类的对象
2)获取对应的运行时类的完整结构(属性、方法、构造器、内部类、父类、所在的包、异常、注解、…)
3)*调用对应的运行时类的指定的结构(属性、方法、构造器)
4)反射的应用:动态代理
public void test3(){ Person p = new Person(); Class clazz = p.getClass();//通过运行时类的对象,调用其getClass(),返回其运行时类。 System.out.println(clazz); } //有了反射,可以通过反射创建一个类的对象,并调用其中的结构 @Test public void test2() throws Exception{ Class clazz = Person.class; // Class clazz1 = String.class; //1.创建clazz对应的运行时类Person类的对象 Person p = (Person)clazz.newInstance(); System.out.println(p); //2.通过反射调用运行时类的指定的属性 //2.1 Field f1 = clazz.getField("name"); f1.set(p,"LiuDeHua"); System.out.println(p); //2.2 Field f2 = clazz.getDeclaredField("age"); f2.setAccessible(true); f2.set(p, 20); System.out.println(p); //3.通过反射调用运行时类的指定的方法 Method m1 = clazz.getMethod("show"); m1.invoke(p); Method m2 = clazz.getMethod("display",String.class); m2.invoke(p,"CHN"); } //在有反射以前,如何创建一个类的对象,并调用其中的方法、属性 @Test public void test1(){ Person p = new Person(); // Person p1 = new Person(); p.setAge(10); p.setName("TangWei"); System.out.println(p); p.show(); // p.display("HK"); } }
获取Class实例的方法
1、调用运行时类本身的.class属性
Class cls=Person.class;
2、通过运行时类的对象获取
Preson p=new Person(); Class cls1=p.getClass();
3、通过Class的静态方法
Class cls=Class。forName("com.item.cn.Person");
4、通过类的加载器
ClassLoder cl=this.getClass().getClassLoder(); Class cls=cl.loadClass(className);
在获取Class的实例后可用通过,newInstance()方法,获取对象实例。
创建对应的运行时类的对象,使用newInstance();要想创建成功要求:
1、对应的运行时类要有空参的构造器,实际上就是调用了运行时类的空参数的构造器
2、构造器的权限修饰付的权限要足够。
所以在创建类时,尽量保留一个空参的构造器。
通过反射调用类的完整结构
1、getFields();只能获取运行时类中声明为Public的属性,包括类中的Public的属性。
2、getDeclaredFields:获取运行时类声明的所有属性,只能获取运行类本身属性,不能获取父类。
field的常见方法
代码:
public class TestField { //获取对应的运行时类的属性 @Test public void test1(){ Class clazz = Person.class; //1.getFields():只能获取到运行时类中及其父类中声明为public的属性 Field[] fields = clazz.getFields(); for(int i = 0;i < fields.length;i++){ System.out.println(fields[i]); } System.out.println(); //2.getDeclaredFields():获取运行时类本身声明的所有的属性 Field[] fields1 = clazz.getDeclaredFields(); for(Field f : fields1){ System.out.println(f.getName()); } } //权限修饰符 变量类型 变量名 //获取属性的各个部分的内容 @Test public void test2(){ Class clazz = Person.class; Field[] fields1 = clazz.getDeclaredFields(); for(Field f : fields1){ //1.获取每个属性的权限修饰符 int i = f.getModifiers(); String str1 = Modifier.toString(i); System.out.print(str1 + " "); //2.获取属性的类型 Class type = f.getType(); System.out.print(type.getName() + " "); //3.获取属性名 System.out.print(f.getName()); 4000 System.out.println(); } } //调用运行时类中指定的属性 @Test public void test3() throws Exception{ Class clazz = Person.class; //1.获取指定的属性 //getField(String fieldName):获取运行时类中声明为public的指定属性名为fieldName的属性 Field name = clazz.getField("name"); //2.创建运行时类的对象 Person p = (Person)clazz.newInstance(); System.out.println(p); //3.将运行时类的指定的属性赋值 name.set(p,"Jerry"); System.out.println(p); System.out.println("%"+name.get(p)); System.out.println(); //getDeclaredField(String fieldName):获取运行时类中指定的名为fieldName的属性 Field age = clazz.getDeclaredField("age"); //由于属性权限修饰符的限制,为了保证可以给属性赋值,需要在操作前使得此属性可被操作。 age.setAccessible(true); age.set(p,10); System.out.println(p); // Field id = clazz.getField("id"); } }
获取运行时类的方法
1、getMethod();获取运行时类及其弗雷中所有的声明为public的方法。
2、getDelecaredMethods();获取运行时类本身声明的方法
还可以获取权限修饰丰富,返回值类型,方法名,星灿列表,异常等
代码:
public class TestMethod { //1.获取运行时类的方法 @Test public void test1(){ Class clazz = Person.class; //1.getMethods():获取运行时类及其父类中所有的声明为public的方法 Method[] m1 = clazz.getMethods(); for(Method m : m1){ System.out.println(m); } System.out.println(); //2.getDeclaredMethods():获取运行时类本身声明的所有的方法 Method[] m2 = clazz.getDeclaredMethods(); for(Method m : m2){ System.out.println(m); } } //注解 权限修饰符 返回值类型 方法名 形参列表 异常 @Test public void test2(){ Class clazz = Person.class; Method[] m2 = clazz.getDeclaredMethods(); for(Method m : m2){ //1.注解 Annotation[] ann = m.getAnnotations(); for(Annotation a : ann){ System.out.println(a); } //2.权限修饰符 String str = Modifier.toString(m.getModifiers()); System.out.print(str + " "); //3.返回值类型 Class returnType = m.getReturnType(); System.out.print(returnType.getName() + " "); //4.方法名 System.out.print(m.getName() + " "); //5.形参列表 System.out.print("("); Class[] params = m.getParameterTypes(); for(int i = 0;i < params.length;i++){ System.out.print(params[i].getName() + " args-" + i + " "); } System.out.print(")"); //6.异常类型 Class[] exps = m.getExceptionTypes(); if(exps.length != 0){ System.out.print("throws "); } for(int i = 0;i < exps.length;i++){ System.out.print(exps[i].getName() + " "); } System.out.println(); } } //调用运行时类中指定的方法 @Test public void test3() throws Exception{ Class clazz = Person.class; //getMethod(String methodName,Class ... params):获取运行时类中声明为public的指定的方法 Method m1 = clazz.getMethod("show"); Person p = (Person)clazz.newInstance(); //调用指定的方法:Object invoke(Object obj,Object ... obj) Object returnVal = m1.invoke(p);//我是一个人 System.out.println(returnVal);//null Method m2 = clazz.getMethod("toString"); Object returnVal1 = m2.invoke(p); System.out.println(returnVal1);//Person [name=null, age=0] //对于运行时类中静态方法的调用 Method m3 = clazz.getMethod("info"); m3.invoke(Person.class); //getDeclaredMethod(String methodName,Class ... params):获取运行时类中声明了的指定的方法 Method m4 = clazz.getDeclaredMethod("display",String.class,Integer.class); m4.setAccessible(true); Object value = m4.invoke(p,"CHN",10);//我的国籍是:CHN System.out.println(value);//10 } }
获取构造器
public class TestConstructor { @Test public void test1() throws Exception{ String className = "com.sus.java.Person"; Class clazz = Class.forName(className); Object obj = clazz.newInstance(); Person p = (Person)obj; System.out.println(p); } @Test public void test2() throws ClassNotFoundException{ String className = "com.sus.java.Person"; Class clazz = Class.forName(className); Constructor[] cons = clazz.getDeclaredConstructors(); for(Constructor c : cons){ System.out.println(c); } } //调用指定的构造器,创建运行时类的对象 @Test public void test3() throws Exception{ String className = "com.atguigu.java.Person"; Class clazz = Class.forName(className); Constructor cons = clazz.getDeclaredConstructor(String.class,int.class); cons.setAccessible(true); Person p = (Person)cons.newInstance("罗伟",20); System.out.println(p); }
反射的应用——动态代理
Proxy :专门完成代理的操作类,是所有动态代理类的父类。通过此类为一个或多个接口动态地生成实现类。
提供用于创建动态代理类和动态代理对象的静态方法
static Class
//动态代理的使用,体会反射是动态语言的关键 interface Subject { void action(); } // 被代理类 class RealSubject implements Subject { public void action() { System.out.println("我是被代理类,记得要执行我哦!么么~~"); } } class MyInvocationHandler implements InvocationHandler { Object obj;// 实现了接口的被代理类的对象的声明 // ①给被代理的对象实例化②返回一个代理类的对象 public Object blind(Object obj) { this.obj = obj; return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj .getClass().getInterfaces(), this); } //当通过代理类的对象发起对被重写的方法的调用时,都会转换为对如下的invoke方法的调用 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //method方法的返回值时returnVal Object returnVal = method.invoke(obj, args); return returnVal; } } public class TestProxy { public static void main(String[] args) { //1.被代理类的对象 RealSubject real = new RealSubject(); //2.创建一个实现了InvacationHandler接口的类的对象 MyInvocationHandler handler = new MyInvocationHandler(); //3.调用blind()方法,动态的返回一个同样实现了real所在类实现的接口Subject的代理类的对象。 Object obj = handler.blind(real); Subject sub = (Subject)obj;//此时sub就是代理类的对象 sub.action();//转到对InvacationHandler接口的实现类的invoke()方法的调用 //再举一例 NikeClothFactory nike = new NikeClothFactory(); ClothFactory proxyCloth = (ClothFactory)handler.blind(nike);//proxyCloth即为代理类的对象 proxyCloth.productCloth(); } }
——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序
- 二叉查找树
- [原创]java局域网聊天系统