Reflection(反射)
动态语言的关键
- 允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法
- 提供的功能:
在运行时判断任意一个对象所属类
在运行时构造任意一个类的对象
在运行时判断任意一个类所具有的成员变量和方法
在运行时调用任意一个对象的成员变量和方法
生成动态代理
例:
Person类
@MyAnnotation(value = "atguigu")
public class Person extends Creature<String> implements Comparable,MyInsterface{ public String name;private int age;//创建类时,尽量保留一个空参的构造器public Person() {super();System.out.print("空参");}public Person(String name) {super();this.name = name;}public Person(String name, int age) {super();this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@MyAnnotation(value = "boos")public void show() {System.out.println("I am Person");}public void display(String nation)throws Exception {System.out.println("我的国籍是= " + nation);}private Integer displays(String nation,Integer i)throws Exception {System.out.println("我的国籍是= " + nation);return i;}@Overridepublic String toString() {return "Person [name=" + name + ", age=" + age + "]";}@Overridepublic int compareTo(Object arg0) {// TODO Auto-generated method stubreturn 0;}public static void info() {System.out.println("Chianese");}class A {}
}
- 没有反射之前,创建对象,调用方法,属性
@Test
public void test1() throws Exception {Person p = new Person();p.setName("HaoJie");p.setAge(22);System.out.println(p); p.show();p.display("中国");
}
- 有反射之后,创建对象,调用方法,属性
@Test
public void test2() throws Exception{Class c = Person.class;//c直接指向Person实体(反射的源头java.lang.Class类)//1.创建c对应的运行时类Person类的对象Person p = (Person)c.newInstance();//2-1.通过反射获取实体的公有属性Field f1 = c.getField("name");f1.set(p,"LiYunHai");System.out.println(p); //2-2.通过反射获取实体的私有属性Field f2 = c.getDeclaredField("age");f2.setAccessible(true);f2.set(p,26);System.out.println(p); //通过反射调用运行时实体(类)的指定的方法Method m1 = c.getMethod("show");m1.invoke(p);Method m2 = c.getMethod("display",String.class);m2.invoke(p,"China");
}
1.理解Class类并实例化Class类对象
-
类的具体实现:
创建类,通过编译(
javac.exe
),生产字节码文件,之后通过java.exe
加载(JVM的类加载器完成的)字节码文件,字节码文件加载到内存中,就是一个运行时类,存在缓冲区中。这个运行时类本身就是一个Class的实例
-
每一个运行时类只加载一次
-
有Class的实例,就可以进行如下操作:
//*创建对应的运行时类的对象//获取对应的运行时类的完整结构(属性,方法,构造器,内部类。。。)//*调用对应运行时类的指定的结构(属性,方法,构造器)//反射的应用:动态代理
获取Class的实例(掌握3种)
@Test
public void test4() throws ClassNotFoundException {//1.调用运行时类本身的.class属性Class clazz = Person.class;System.out.println(clazz.getName()); Class clazz1 = String.class;System.out.println(clazz1.getName());System.out.println();//2.通过运行时类的对象获取Person p = new Person();Class clazz2 = p.getClass();System.out.println(clazz2.getName());//3.通过Class的静态方法获取String classname = "java.lang.String";Class clazz3 = Class.forName(classname);System.out.println(clazz3.getName());//4.(了解)通过类的加载器ClassLoader classLoader = this.getClass().getClassLoader();Class clazz4 = classLoader.loadClass(classname);System.out.println(clazz4.getName());System.out.println(clazz1 == clazz3);//trueSystem.out.println(clazz1 == clazz2);//falseSystem.out.println(clazz1 == clazz4);//true
}
例:
@Test public void test5() throws IOException {ClassLoader loader1 = ClassLoader.getSystemClassLoader(); System.out.println(loader1);//获取ClassLoader类的加载类AppClassLoaderClassLoader loader2 = loader1.getParent();System.out.println(loader2);//ExtClassLoaderClassLoader loader3 = loader2.getParent();System.out.println(loader3);//null(核心类库及引导类无法获取)Class clazz1 = Person.class;ClassLoader loader4 = clazz1.getClassLoader();System.out.println(loader4);//AppClassLoader}
//掌握如下:查找包下的文件中的部分内容ClassLoader loader5 = this.getClass().getClassLoader(); InputStream is = loader5.getResourceAsStream("hello.txt");//查找工程下的文件中的部分内容//FileInputStream is = new FileInputStream(new File("hello.txt"));Properties txt = new Properties();txt.load(is);String name = txt.getProperty("user");System.out.println(name);String password = txt.getProperty("password");System.out.println(password);
2.在运行时创建类对象并获取类的完整结构
例:
@Testpublic void test1() throws Exception {String className = "Person"; Class clazz = Class.forName(className); //创建对应的运行类的对象//要求:1.对应的运行时类要有空参的构造器;2.构造器的权限应在缺省(及以上)Object obj = clazz.newInstance();Person p = (Person)obj;System.out.print(p); }@Test//构造器public void test2() throws ClassNotFoundException {String className = "Person"; Class clazz = Class.forName(className); //getDeclaredConstructors():获取本身类所有的构造器Constructor[] cons = clazz.getDeclaredConstructors();for(Constructor c : cons) { System.out.println(c); }}
获取运行时类的方法
@Testpublic 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.获取运行时类本身声明的所有方法Method[] m2 = clazz.getDeclaredMethods();for(Method m : m2) {System.out.println(m);}System.out.println();System.out.println();}
获取对应的运行时类的属性
@Testpublic void test1() {Class clazz = Person.class;//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());}}
获取属性各个部分的内容(权限修饰符 变量类型 变量名)
@Testpublic void test2() {Class clazz = Person.class;Field[] fields = clazz.getDeclaredFields();for(Field f : fields) {//1.获取属性的权限修饰符int i = f.getModifiers();String str = Modifier.toString(i);System.out.print(str + " "); //2.获取属性的类型Class type = f.getType();System.out.print(type.getName() + " ");//3.获取属性名System.out.print(f.getName());System.out.println();}}
注解 权限修饰符 返回值类型 方法名 形参列表 异常
@Testpublic void test2() {Class clazz = Person.class;Method[] m1 = clazz.getDeclaredMethods();for(Method m : m1) { //1.注解Annotation[] ann = m.getAnnotations();for(Annotation an : ann) {System.out.println(an);}//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();}}
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.*;
@Target({TYPE,FIELD,METHOD,PARAMETER,CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {String value();
}
带泛型的类
public class Creature<T> {public double weight; public void breath() {System.out.println("呼吸");}
}
接口
import java.io.Serializable;public interface MyInsterface extends Serializable{}
继承,实现接口等
@MyAnnotation(value = "atguigu")
public class Person extends Creature<String> implements Comparable,MyInsterface{ public String name;private int age;//创建类时,尽量保留一个空参的构造器public Person() {super();System.out.print("空参");}public Person(String name) {super();this.name = name;}public Person(String name, int age) {super();this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@MyAnnotation(value = "boos")public void show() {System.out.println("I am Person");}public void display(String nation)throws Exception {System.out.println("我的国籍是= " + nation);}private Integer displays(String nation,Integer i)throws Exception {System.out.println("我的国籍是= " + nation);return i;}@Overridepublic String toString() {return "Person [name=" + name + ", age=" + age + "]";}@Overridepublic int compareTo(Object arg0) {// TODO Auto-generated method stubreturn 0;}public static void info() {System.out.println("Chianese");}class A {}
}
测试
import java.lang.annotation.Annotation;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type; import org.junit.Test;public class TestOther {@Test//1.获取运行时类的父类public void test1() {Class clazz = Person.class;Class superClass = clazz.getSuperclass();System.out.println(superClass);//class Creature }@Test//2.获取带泛型的父类public void test2() {Class clazz = Person.class;Type type = clazz.getGenericSuperclass();System.out.println(type);//Creature<java.lang.String> }@Test//3.获取父类的泛型public void test3() {Class clazz = Person.class;Type type = clazz.getGenericSuperclass();ParameterizedType param = (ParameterizedType)type; Type[] ars = param.getActualTypeArguments(); System.out.println(((Class)ars[0]).getName()); }@Test//获取实现的接口public void test4() {Class clazz = Person.class;Class[] interfaces = clazz.getInterfaces(); for(Class i : interfaces) { System.out.println(i); }}@Test//获取所在的包public void test5() {Class clazz = Person.class;Package pack = clazz.getPackage();System.out.println(pack); }@Test//获取注解public void test6() {Class clazz = Person.class;Annotation[] anns = clazz.getAnnotations();for(Annotation a : anns) {System.out.println(a); }}
}
3.通过反射调用类的指定方法,指定属性
调用指定构造器,创建对象
@Test//public void test3() throws Exception {String className = "Person"; Class clazz = Class.forName(className);Constructor cons = clazz.getDeclaredConstructor(String.class,int.class);cons.setAccessible(true);Person p = (Person)cons.newInstance("李福根",56);System.out.println(p);}
调用运行时类中指定的属性
@Testpublic void test3() throws Exception {Class clazz = Person.class;//1.获取指定的属性//getField(String fielName):获取运行时类中声明为public类型的指定属性名为fielName的属性Field name = clazz.getField("name");//2.创建运行时类的对象Person p = (Person)clazz.newInstance();System.out.println(p); //3.将运行时指定的属性赋值name.set(p, "Jame");System.out.println(p);System.out.println();//getDeclaredField(String fielName):获取运行时类中指定属性名为fielName的属性Field age = clazz.getDeclaredField("age");//私有属性不能直接用getField来调//由于权限修饰符的限制,为保证可以给属性赋值,需要在操作前使此属性可被操作(缺省状态下,可不用)age.setAccessible(true);age.set(p, 25);System.out.println(p);}
调用运行时类的指定方法
@Testpublic 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);//方法本身无返回值,就显示为nullSystem.out.println(returnVal);Method m2 = clazz.getMethod("toString");Object returnVal1 = m2.invoke(p);System.out.println(returnVal1);//方法本身有返回值,就显示为方法的返回值//调用静态的方法Method m3 = clazz.getMethod("info");m3.invoke(Person.class);//不需要对象//getDeclaredMethod(String methodName,Class .. params):获取运行时类中声明的指定方法Method m4 = clazz.getDeclaredMethod("displays",String.class,Integer.class);m4.setAccessible(true);Object returnVal2 = m4.invoke(p,"CNN",10);//调用方法System.out.println(returnVal2);//返回值}
4.动态代理与AOP
静态代理
例:
package Proxy;
//接口
interface ClothFactory{void productCloth();
}
//被代理类
class NikeClothFactory implements ClothFactory{@Overridepublic void productCloth() {System.out.println("Nike工厂开工了!"); }
}//代理类
class ProxyFactory implements ClothFactory{ClothFactory cf;//创建代理类的对象时,实际传入一个被代理类的对象public ProxyFactory(ClothFactory cf) {this.cf = cf;}@Overridepublic void productCloth() {System.out.println("代理开始,收专利费了!");cf.productCloth();}}
public class TestCiothProduct {public static void main(String[] args) { NikeClothFactory nike = new NikeClothFactory();//被代理类ProxyFactory proxy = new ProxyFactory(nike);//代理类proxy.productCloth();
}
}
动态代理
例:
package Proxy; import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;//动态代理
interface Subject{void action();
}
//被代理类
class ReaSubject implements Subject{public void action() {System.out.println("我是被代理类,好囧ing");}
}class MyInvocationHandler implements InvocationHandler{Object obj;//实现接口的被代理类对象的声明//给被代理的对象实例化;返回一个代理类的对象声明public Object blind(Object obj) {this.obj = obj;return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),this);}@Override//当通过代理类的对象发起被重写的方法的调用时,都会转换为对如下invoke方法的调用public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//method方法的返回值是returnValSystem.out.println("代理------");Object returnVal = method.invoke(obj, args);return returnVal;}
}
public class dongProxy {public static void main(String[] args) {//1.被代理类的对象ReaSubject real = new ReaSubject();//2.创建实现InvocationHandler接口的类对象MyInvocationHandler handler = new MyInvocationHandler();//3.调用blind()方法,动态的返回一个同样实现了real所在类实现的接口Subject的代理类的对象Object obj = handler.blind(real);Subject sub = (Subject)obj;//此时的sub就是代理类的对象sub.action();//跳转到InvocationHandler接口的实现类的invoke()方法的调用//例NikeClothFactory nike = new NikeClothFactory();//被代理类ClothFactory proxyCloth = (ClothFactory)handler.blind(nike);//proxyCloth即为代理类的对象proxyCloth.productCloth();}
}
动态代理与AOP
例:
package com.al.java;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;interface Human{void info();void fly();
}
//被代理类
class SuperMan implements Human{public void info() {System.out.println("我是超人");}public void fly() {System.out.println("I believe I can fly!");}
}
class HumanUtil{public void method1() {System.out.println("========方法一======");}public void method2() {System.out.println("========方法二======");}
}class MyInvocationHandler implements InvocationHandler{Object obj;public void setObject(Object obj) {this.obj = obj;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {HumanUtil h = new HumanUtil();h.method1();Object returnval = method.invoke(obj, args);h.method2();return returnval;}}class MyProxy{//动态的创建一个代理类对象public static Object getProxyInstance(Object obj) {MyInvocationHandler handler = new MyInvocationHandler();handler.setObject(obj);return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),handler);}
}public class TestAOP {public static void main(String[] args) { SuperMan man = new SuperMan();//创建被代理类对象Object obj = MyProxy.getProxyInstance(man);//返回代理类对象Human hu = (Human)obj;hu.info();//通过代理类的对象调用重写的抽象方法System.out.println();hu.fly();}
}
运行示例
感谢大家的支持,关注,评论,点赞!
参考资料:
尚硅谷宋红康20天搞定Java基础下部