一:介绍
1.大纲
#1
允许程序在执行期间,调用反射API取得任何类的内部信息,并且可以直接操作任何对象的内部属性和方法。
#2
学习反射,需要掌握的知识点:
*实例化class类
*获取类的完整结构
*通过反射调用类的属性和方法
*动态代理
2.涉及到的一些API
java.lang.Class 类
java.lang.reflect.Field 属性
java.lang.reflect.Method 方法
java.lang.reflect.Constructor 构造器
二:简单反射的小示例(可以直接看后面的内容)
1.新建要反射的类Person
这个要被反射的类中不含有父类,接口,注解等额外的部分,只是一个特别简单的可以被用来反射的类,用来做演示。
1 package demo2; 2 public class Person1 { 3 //这里为了说明反射,权限为public 4 public String name; 5 //这里为了说明反射,做对比,权限为private 6 private int age; 7 8 public Person1() { 9 super(); 10 } 11 public Person1(String name) { 12 super(); 13 this.name = name; 14 } 15 public Person1(int age) { 16 super(); 17 this.age = age; 18 } 19 public String getName() { 20 return name; 21 } 22 public void setName(String name) { 23 this.name = name; 24 } 25 public int getAge() { 26 return age; 27 } 28 public void setAge(int age) { 29 this.age = age; 30 } 31 @Override 32 public String toString() { 33 return "Person1 [name=" + name + ", age=" + age + "]"; 34 } 35 //两个普通的方法 36 //不带参数的函数 37 public void show(){ 38 System.out.println("this is person class"); 39 } 40 //带参数的函数 41 public void diaplay(String nation){ 42 System.out.println("contry is "+nation); 43 } 44 45 }
2.反射的测试
这个部分包括建立反射源
通过反射设置属性
通过反射调用方法函数
1 package demo2; 2 3 import java.lang.reflect.Field; 4 import java.lang.reflect.Method; 5 6 public class Test1 { 7 8 public static void main(String[] args)throws Exception { 9 reflectMethod(); 10 } 11 public static void reflectMethod()throws Exception{ 12 //产生对应的类 13 Class clazz=Person1.class; 14 Person1 p=(Person1)clazz.newInstance(); 15 System.out.println(p); 16 System.out.println("-------------------------"); 17 18 //设置public权限的属性 19 Field f=clazz.getField("name"); 20 f.set(p, "zhangsan"); 21 System.out.println(p); 22 System.out.println("-------------------------"); 23 24 //设置private权限的属性 25 Field f1=clazz.getDeclaredField("age"); 26 f1.setAccessible(true);//增加访问权限 27 f1.set(p, 90); 28 System.out.println(p); 29 System.out.println("-------------------------"); 30 31 //调用不带参数的函数方法 32 Method m=clazz.getMethod("show"); 33 m.invoke(p); 34 System.out.println("-------------------------"); 35 36 //调用带参数的函数方法 37 Method m1=clazz.getMethod("diaplay",String.class); 38 m1.invoke(p, "China"); 39 } 40 }
3.运行结果
-----------------------------------------------------------------------------------------------#反射重点#---------------------------------------------------------------------------------------------------
三:实现Class类的四种实现方式(所有反射的基础源头---class类的获取)
1.介绍四种方式获取要反射类的class文件
*用运行时类本身的.class获取
*通过运行时类的对象的获取
*以class的静态方法获取
*通过类的加载器获取
2.程序
1 package demo2; 2 3 import org.junit.Test; 4 5 public class Test2 { 6 @Test 7 public void classMethod() throws ClassNotFoundException{ 8 //通过类的class文件 9 Class c1=Person1.class; 10 System.out.println(c1); 11 12 //通过运行时类的对象获取class文件 13 Person1 p=new Person1(); 14 Class c2=p.getClass(); 15 System.out.println(c2); 16 17 //通过class的静态方法 18 String name="demo2.Person1"; 19 Class c3=Class.forName(name); 20 System.out.println(c3); 21 22 //通过类的加载器获得class 23 ClassLoader classLoader=this.getClass().getClassLoader(); 24 Class c4=classLoader.loadClass(name); 25 System.out.println(c4); 26 } 27 28 }
3.运行结果
结果看到:四种方式都可以获得class类。
四:类的加载器(解释一下上面方式四中类的加载器,次要内容)
1.介绍
2.程序验证
1 package demo2; 2 import org.junit.Test; 3 public class Test3 { 4 @Test 5 public void show(){ 6 //systemClassLoader 7 ClassLoader c1=ClassLoader.getSystemClassLoader(); 8 System.out.println(c1); 9 10 //ExterSionClassLoader 11 ClassLoader c2=c1.getParent(); 12 System.out.println(c2); 13 14 //null(这一个类加载器不会被获取) 15 ClassLoader c3=c2.getParent(); 16 System.out.println(c3); 17 18 } 19 }
3.运行结果
4.在方式四种使用的是哪一个加载器(程序验证)
1 package demo2; 2 import org.junit.Test; 3 public class Test4 { 4 @Test 5 public void method(){ 6 String name="demo2.Person1"; 7 ClassLoader classLoader=this.getClass().getClassLoader(); 8 System.out.println(classLoader); 9 } 10 }
5.运行结果
五:创建运行时类对象(class文件的基础上)
1.要求
要反射的类中有空参的构造器(最好是这样)
构造器的权限为public
2.程序实现解释
1 package demo2; 2 public class Test5 { 3 public static void main(String[] args)throws Exception { 4 Class c=Person1.class; 5 Object obj=c.newInstance(); 6 Person1 p=(Person1)obj; 7 System.out.println(p); 8 } 9 }
3.运行结果
六:重新构建复杂的即将被反射的类
1.构建复杂的类对象
包含:
*父类
*多接口
*注解
*内部类
*异常
首先是父类:
1 package com.at.java; 2 3 public class Creature<T>{ 4 public double weight; 5 public void breath(){ 6 System.out.println("呼吸"); 7 } 8 }
自定义接口:
1 package com.at.java; 2 3 import java.io.Serializable; 4 public interface MyInterface extends Serializable{ 5 6 }
自定义注解:
1 package com.at.java; 2 import static java.lang.annotation.ElementType.CONSTRUCTOR; 3 import static java.lang.annotation.ElementType.FIELD; 4 import static java.lang.annotation.ElementType.LOCAL_VARIABLE; 5 import static java.lang.annotation.ElementType.METHOD; 6 import static java.lang.annotation.ElementType.PARAMETER; 7 import static java.lang.annotation.ElementType.TYPE; 8 import java.lang.annotation.Retention; 9 import java.lang.annotation.RetentionPolicy; 10 import java.lang.annotation.Target; 11 12 @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE}) 13 @Retention(RetentionPolicy.RUNTIME) 14 public @interface MyAnnotation { 15 String value(); 16 }
反射的类:
1 package com.at.java; 2 3 @MyAnnotation(value = "atguigu") 4 public class Person extends Creature<String> implements Comparable,MyInterface{ 5 public String name; 6 private int age; 7 int id; 8 public Person() { 9 super(); 10 } 11 public Person(String name) { 12 super(); 13 this.name = name; 14 } 15 private Person(String name, int age) { 16 super(); 17 this.name = name; 18 this.age = age; 19 } 20 public String getName() { 21 return name; 22 } 23 public void setName(String name) { 24 this.name = name; 25 } 26 public int getAge() { 27 return age; 28 } 29 public void setAge(int age) { 30 this.age = age; 31 } 32 33 public int getId() { 34 return id; 35 } 36 public void setId(int id) { 37 this.id = id; 38 } 39 @MyAnnotation(value = "abc123") 40 public void show(){ 41 System.out.println("this is person"); 42 } 43 44 private Integer display(String nation,Integer i) throws Exception{ 45 System.out.println("国籍:" + nation); 46 return i; 47 } 48 @Override 49 public String toString() { 50 return "Person [name=" + name + ", age=" + age + "]"; 51 } 52 @Override 53 public int compareTo(Object o) { 54 // TODO Auto-generated method stub 55 return 0; 56 } 57 58 public static void info(){ 59 System.out.println("信息"); 60 } 61 62 class Bird{ 63 64 } 65 66 }
七:获取以及调用类的属性
包括:
*所有属性的获取
*指定属性的调用
1.获取对应类运行时的属性
包括两种;
*getFields():只能获取到运行时类中及其父类中声明为public的属性
*getDeclaredFields():获取运行时类本身声明的所有的属性
1 package com.at.java; 2 import java.lang.reflect.Field; 3 public class Test1 { 4 public static void main(String[] args){ 5 get1(); 6 System.out.println("###################"); 7 get2(); 8 } 9 /** 10 * getFields():只能获取到运行时类中及其父类中声明为public的属性 11 */ 12 public static void get1(){ 13 Class clazz=Person.class; 14 Field[] f=clazz.getFields(); 15 for(int i=0;i<f.length;i++){ 16 System.out.println(f[i].getName()); 17 } 18 } 19 /** 20 * getDeclaredFields():获取运行时类本身声明的所有的属性 21 */ 22 public static void get2(){ 23 Class clazz=Person.class; 24 Field[] f=clazz.getDeclaredFields(); 25 for(Field ff:f){ 26 System.out.println(ff.getName()); 27 } 28 } 29 }
2.运行结果
使用###进行将两种方式进行隔离。
3.获取对应类运行时的属性的各个部分的内容
主要包括:
*权限
*变量名
*变量名
1 package com.at.java; 2 3 import java.lang.reflect.Field; 4 import java.lang.reflect.Modifier; 5 6 public class Test2 { 7 8 public static void main(String[] args) { 9 get2(); 10 11 } 12 /** 13 * getDeclaredFields():获取运行时类本身声明的所有的属性的各个部分 14 */ 15 public static void get2(){ 16 Class clazz=Person.class; 17 Field[] f=clazz.getDeclaredFields(); 18 for(Field ff:f){ 19 //属性权限 20 int num=ff.getModifiers(); 21 String str=Modifier.toString(num); 22 System.out.print(str+" "); 23 24 //属性类型 25 Class type=ff.getType(); 26 System.out.print(type.getName()+" "); 27 28 //属性变量名 29 System.out.println(ff.getName()); 30 } 31 } 32 33 }
4.运行结果
5.调用设置指定属性
注意点事权限问题
1 package com.at.java; 2 3 import java.lang.reflect.Field; 4 5 public class Test6 { 6 public static void main(String[] args)throws Exception { 7 Class clazz=Person.class; 8 /** 9 * 属性权限为public 10 */ 11 Field name = clazz.getField("name"); 12 Person p = (Person)clazz.newInstance(); 13 //将运行时类的指定的属性赋值 14 name.set(p,"Jerry"); 15 System.out.println(p); 16 //将运行时类的指定的属性赋值后再取出 17 System.out.println("name="+name.get(p)); 18 19 System.out.println("########################"); 20 /** 21 * 属性权限为private 22 */ 23 Field age = clazz.getDeclaredField("age"); 24 age.setAccessible(true);//由于属性权限修饰符的限制,需要在操作前使得此属性可被操作。 25 age.set(p,10); 26 System.out.println(p); 27 28 System.out.println("#######################"); 29 /** 30 * 属性的权限为默认default 31 * 这个set时不需要setAccessible(true)。 32 */ 33 Field id = clazz.getDeclaredField("id"); 34 id.set(p,3); 35 System.out.println(p); 36 } 37 }
6.运行结果
八:获取与调用对应类运行时的方法
包括两种:
*获取所有方法
*调用指定方法
1.获取对应类运行时的方法
包括两种:
*getMethods():获取运行时类及其父类中所有的声明为public的方法
*getDeclaredMethods():获取运行时类本身声明的所有的方法
1 package com.at.java; 2 import java.lang.reflect.Method; 3 public class Test3 { 4 public static void main(String[] args) { 5 get1(); 6 System.out.println("#############"); 7 get2(); 8 } 9 /** 10 * getMethods():获取运行时类及其父类中所有的声明为public的方法 11 */ 12 public static void get1(){ 13 Class clazz=Person.class; 14 Method[] m=clazz.getMethods(); 15 for(Method mm: m){ 16 System.out.println(mm.getName()); 17 } 18 } 19 /** 20 * getDeclaredMethods():获取运行时类本身声明的所有的方法 21 */ 22 public static void get2(){ 23 Class clazz=Person.class; 24 Method[] m=clazz.getDeclaredMethods(); 25 for(Method mm:m){ 26 System.out.println(mm.getName()); 27 } 28 } 29 }
2.运行结果
3.获取对应类运行时的方法的各个部分
包括:
*注解
*权限
*返回类型
*方法名
*参数列表
*异常类型
1 package com.at.java; 2 3 import java.lang.annotation.Annotation; 4 import java.lang.reflect.Method; 5 import java.lang.reflect.Modifier; 6 7 public class Test4 { 8 9 public static void main(String[] args) { 10 get2(); 11 } 12 /** 13 * 注解 权限修饰符 返回值类型 方法名 形参列表 异常 14 */ 15 public static void get2(){ 16 Class clazz = Person.class; 17 Method[] m2 = clazz.getDeclaredMethods(); 18 for(Method m : m2){ 19 //1.注解 20 Annotation[] ann = m.getAnnotations(); 21 for(Annotation a : ann){ 22 System.out.println(a); 23 } 24 25 //2.权限修饰符 26 String str = Modifier.toString(m.getModifiers()); 27 System.out.print(str + " "); 28 29 //3.返回值类型 30 Class returnType = m.getReturnType(); 31 System.out.print(returnType.getName() + " "); 32 33 //4.方法名 34 System.out.print(m.getName() + " "); 35 36 //5.形参列表 37 System.out.print("("); 38 Class[] params = m.getParameterTypes(); 39 for(int i = 0;i < params.length;i++){ 40 System.out.print(params[i].getName() + " args-" + i + " "); 41 } 42 System.out.print(")"); 43 44 //6.异常类型 45 Class[] exps = m.getExceptionTypes(); 46 if(exps.length != 0){ 47 System.out.print("throws "); 48 } 49 for(int i = 0;i < exps.length;i++){ 50 System.out.print(exps[i].getName() + " "); 51 } 52 System.out.println(); 53 } 54 } 55 }
4.运行结果
5.调用指定方法
1 package com.at.java; 2 import java.lang.reflect.Method; 3 public class Test7 { 4 public static void main(String[] args) throws Exception{ 5 Class clazz = Person.class; 6 Person p = (Person)clazz.newInstance(); 7 /** 8 * public 9 */ 10 Method m1 = clazz.getMethod("show"); 11 Object returnVal = m1.invoke(p); 12 System.out.println(returnVal); //因为返回值为void,所以打印为null 13 14 Method m2 = clazz.getMethod("toString"); 15 Object returnVal1 = m2.invoke(p); //因为返回值为string,所以这样调用不会有什么现象 16 System.out.println(returnVal1); //没有现象,所以打印就是打印返回值 17 18 /** 19 * private 20 * 同时,这是带参数的函数 21 */ 22 Method m4 = clazz.getDeclaredMethod("display",String.class,Integer.class); 23 m4.setAccessible(true); 24 Object value = m4.invoke(p,"CHN",10); 25 System.out.println(value); 26 27 /** 28 * static 方法,单独提出来 29 */ 30 Method m3 = clazz.getMethod("info"); 31 m3.invoke(Person.class); 32 } 33 }
6.运行结果
九:获取构造器
包括:
*所有的构造器
*调用指定的构造器
1.获取所有的构造器
1 package com.at.java; 2 import java.lang.reflect.Constructor; 3 public class Test8 { 4 public static void main(String[] args) throws Exception{ 5 String className = "com.at.java.Person"; 6 Class clazz = Class.forName(className); 7 /** 8 * 获取所有的构造器 9 */ 10 Constructor[] cons = clazz.getDeclaredConstructors(); 11 for(Constructor c : cons){ 12 System.out.println(c); 13 } 14 } 15 }
2.运行结果
3.调用指定的构造器
1 package com.at.java; 2 import java.lang.reflect.Constructor; 3 public class Test9 { 4 public static void main(String[] args)throws Exception{ 5 String className = "com.at.java.Person"; 6 Class clazz = Class.forName(className); 7 /** 8 * 调用String,int的构造器 9 */ 10 Constructor cons = clazz.getDeclaredConstructor(String.class,int.class); 11 cons.setAccessible(true); 12 Person p = (Person)cons.newInstance("罗伟",20); 13 System.out.println(p); 14 } 15 }
4.运行结果
十:获取其他的内容(父类,接口,注解,包,)
1.程序
1 package com.at.java; 2 import java.lang.annotation.Annotation; 3 import java.lang.reflect.ParameterizedType; 4 import java.lang.reflect.Type; 5 import org.junit.Test; 6 7 public class Test10 { 8 //6.获取注解 9 @Test 10 public void test6(){ 11 Class clazz = Person.class; 12 Annotation[] anns = clazz.getAnnotations(); 13 for(Annotation a : anns){ 14 System.out.println(a); 15 } 16 } 17 18 //5.获取所在的包 19 @Test 20 public void test5(){ 21 Class clazz = Person.class; 22 Package pack = clazz.getPackage(); 23 System.out.println(pack); 24 } 25 26 //4.获取实现的接口 27 @Test 28 public void test4(){ 29 Class clazz = Person.class; 30 Class[] interfaces = clazz.getInterfaces(); 31 for(Class i : interfaces){ 32 System.out.println(i); 33 } 34 } 35 36 //3*.获取父类的泛型 37 @Test 38 public void test3(){ 39 Class clazz = Person.class; 40 Type type1 = clazz.getGenericSuperclass(); 41 42 ParameterizedType param = (ParameterizedType)type1; 43 Type[] ars = param.getActualTypeArguments(); 44 45 System.out.println(((Class)ars[0]).getName()); 46 } 47 48 //2.获取带泛型的父类 49 @Test 50 public void test2(){ 51 Class clazz = Person.class; 52 Type type1 = clazz.getGenericSuperclass(); 53 System.out.println(type1); 54 } 55 56 //1.获取运行时类的父类 57 @Test 58 public void test1(){ 59 Class clazz = Person.class; 60 Class superClass = clazz.getSuperclass(); 61 System.out.println(superClass); 62 } 63 }
2.运行结果
十一:动态代理
1.静态代理
1 /** 2 * 静态代理模式 3 */ 4 package com.at.java1; 5 //接口 6 interface ClothFactory{ 7 void productCloth(); 8 } 9 10 //被代理类 11 class NikeClothFactory implements ClothFactory{ 12 @Override 13 public void productCloth() { 14 System.out.println("Nike"); 15 } 16 public void productCloth2() { 17 System.out.println("Nike2"); 18 } 19 } 20 21 //代理类 22 class ProxyFactory implements ClothFactory{ 23 //引用 24 ClothFactory cf; 25 public ProxyFactory(ClothFactory cf){ //创建代理类的对象时,实际传入一个被代理类的对象 26 this.cf = cf; 27 } 28 29 @Override 30 public void productCloth() { 31 System.out.println("一共$1000"); 32 cf.productCloth(); //实际在代理类中执行的还是被代理类的方法 33 } 34 35 } 36 37 public class TestClothProduct { 38 public static void main(String[] args) { 39 NikeClothFactory nike = new NikeClothFactory(); 40 ProxyFactory proxy = new ProxyFactory(nike); //将被代理类传入代理类中 41 proxy.productCloth(); 42 } 43 }
2.运行结果
3.动态代理
1 /** 2 * 动态代理 3 */ 4 package com.at.java1; 5 import java.lang.reflect.InvocationHandler; 6 import java.lang.reflect.Method; 7 import java.lang.reflect.Proxy; 8 //接口 9 interface Subject { 10 void action(); 11 } 12 //被代理类 13 class RealSubject implements Subject { 14 public void action() { 15 System.out.println("我是被代理类,记得要执行我哦!"); 16 } 17 } 18 19 //代理类 20 //动态代理都要实现接口InvocationHandler 21 class MyInvocationHandler implements InvocationHandler { 22 Object obj; 23 //①给被代理的对象实例化②返回一个代理类的对象 24 public Object blind(Object obj) { 25 this.obj = obj; 26 return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj 27 .getClass().getInterfaces(), this); 28 } 29 30 //当通过代理类的对象发起对被重写的方法的调用时,都会转换为对如下的invoke方法的调用 31 @Override 32 public Object invoke(Object proxy, Method method, Object[] args)throws Throwable { 33 Object returnVal = method.invoke(obj, args); 34 return returnVal; 35 } 36 } 37 38 public class TestProxy { 39 public static void main(String[] args) { 40 RealSubject real = new RealSubject(); 41 MyInvocationHandler handler = new MyInvocationHandler(); 42 //动态的返回一个同样实现了real所在类实现的接口Subject的代理类的对象。 43 Object obj = handler.blind(real); 44 Subject sub = (Subject)obj; 45 sub.action(); 46 } 47 }
4.运行结果
十二:动态代理与静态代理的区别
2017.12.21,今天查看了一下他们之间的区别,在这篇文章中解释的挺好的,就没有重新整理,直接粘贴一下链接。
http://blog.csdn.net/hejingyuan6/article/details/36203505。
在这篇文章中,这一段比我上面的程序写的更好理解: