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;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
@Override
public int compareTo(Object arg0) {
// TODO Auto-generated method stub
return 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);//true
System.out.println(clazz1 == clazz2);//false
System.out.println(clazz1 == clazz4);//true
}
例:
@Test
public void test5() throws IOException {
ClassLoader loader1 = ClassLoader.getSystemClassLoader();
System.out.println(loader1);//获取ClassLoader类的加载类AppClassLoader
ClassLoader loader2 = loader1.getParent();
System.out.println(loader2);//ExtClassLoader
ClassLoader 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.在运行时创建类对象并获取类的完整结构
例:
@Test
public 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);
}
}
获取运行时类的方法
@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.获取运行时类本身声明的所有方法
Method[] m2 = clazz.getDeclaredMethods();
for(Method m : m2) {
System.out.println(m);
}
System.out.println();
System.out.println();
}
获取对应的运行时类的属性
@Test
public 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());
}
}
获取属性各个部分的内容(权限修饰符 变量类型 变量名)
@Test
public 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();
}
}
注解 权限修饰符 返回值类型 方法名 形参列表 异常
@Test
public 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;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
@Override
public int compareTo(Object arg0) {
// TODO Auto-generated method stub
return 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);
}
调用运行时类中指定的属性
@Test
public 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);
}
调用运行时类的指定方法
@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);//方法本身无返回值,就显示为null
System.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{
@Override
public void productCloth() {
System.out.println("Nike工厂开工了!");
}
}
//代理类
class ProxyFactory implements ClothFactory{
ClothFactory cf;
//创建代理类的对象时,实际传入一个被代理类的对象
public ProxyFactory(ClothFactory cf) {
this.cf = cf;
}
@Override
public 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方法的返回值是returnVal
System.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;
}
@Override
public 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基础下部