Java笔记_22(反射和动态代理)

一、反射

1.1、反射的概述

什么是反射?

反射允许对成员变量,成员方法和构造方法的信息进行编程访问
在这里插入图片描述

1.2、获取class对象的三种方式

  1. Class.forName(“全类名”);
    • 全类名:包名+类名
  2. 类名.class
  3. 对象.getclass()
    在这里插入图片描述
package reflect.Dome1;

public class Dome {
    public static void main(String[] args) throws ClassNotFoundException {
        //方式一
        Class aClass = Class.forName("reflect.Dome1.student");
        System.out.println(aClass);

        //方式二
        Class aClass1 = student.class;
        System.out.println(aClass1);//与方式一的结果相同

        student s = new student();
        Class aClass2 = s.getClass();
        System.out.println(aClass2);//三个方式结果相同
    }
}
package reflect.Dome1;

public class student {
    private String name;
    private int age;

    public student() {
    }

    public student(String name, int age) {
        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;
    }

    public String toString() {
        return "student{name = " + name + ", age = " + age + "}";
    }
}

1.3、反射获取构造方法

Class类中用于获取构造方法的方法

方法名称说明
Constructor<?>[ ] getConstructors()返回所有公共构造方法对象的数组
Constructor<?>[ ] getDeclaredConstructors()返回所有构造方法对象的数组
Constructor<T> getConstructor(Class<?>… parameterTypes)返回单个公共构造方法对象
Constructor<T> getDeclaredConstructor(Class<?>… parameterTypes)返回单个构造方法对象

Constructor类中用于创建对象的方法

方法名称说明
T newlnstance(Object… initargs)根据指定的构造方法创建对象
setAccessible(boolean flag)设置为true,表示取消访问权限
package reflect.Dome2;



import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class dome {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class class1 = Class.forName("reflect.Dome2.student");

        Constructor[] constructors = class1.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }

        Constructor con = class1.getDeclaredConstructor(String.class,int.class);
        System.out.println(con);

        Constructor[] declaredConstructors = class1.getDeclaredConstructors();
        for (Constructor declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor);
        }
        //如果是私有构造方法,则不能直接使用,只能看到
        //通过添加setAccessible方法,暴力取消临时权限校验。就可以使用
        con.setAccessible(true);
        student stu = (student) con.newInstance("张三", 21);
        System.out.println(stu);
    }
}
package reflect.Dome2;

public class student {
    private String name;
    private int age;

    public student() {
    }

    private student(String name, int age) {
        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;
    }

    public String toString() {
        return "student{name = " + name + ", age = " + age + "}";
    }
}

1.4、反射获取成员变量

Class类中用于获取成员变量的方法

方法名称说明
Field[] getFields()返回所有公共成员变量对象的数组
Field[] getDeclaredFields()返回所有成员变量对象的数组
Field getField(String name)返回单个公共成员变量对象
Field getDeclaredField(String name)返回单个成员变量对象

Field类中用于创建对象的方法

方法名称说明
void set(Object obj, Object value)赋值
Object get(Object obj)获取值
package reflect.Dome3;

import java.lang.reflect.Field;

public class dome {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
        Class clazz = Class.forName("reflect.Dome3.Student");

        //获取到公共成员变量
        Field[] fields = clazz.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }
        //查找该成员变量
        Field gender = clazz.getField("gender");
        System.out.println(gender);

        //获取所有的成员变量
        Field[] declaredField = clazz.getDeclaredFields();
        for (Field field : declaredField) {
            System.out.println(field);
        }

        //获取私有变量
        Field name = clazz.getDeclaredField("name");
        System.out.println(name);

        //获取权限修饰符
        int modifiers = name.getModifiers();
        System.out.println(modifiers);
        //获取成员变量的名称
        String name1 = name.getName();
        System.out.println(name1);
        //获取成员变量的类型
        Class<?> type = name.getType();
        System.out.println(type);
        //创建一个对象
        Student s = new Student("张三",23,"男");
        name.setAccessible(true);
        Object o = name.get(s);
        System.out.println(o);
        //修改s里面name的值
        name.set(s,"小王");
        System.out.println(s);
    }
}
package reflect.Dome3;

public class Student {
    private String name;
    private int age;
    public String gender;


    public Student() {
    }

    public Student(String name, int age, String gender) {
        this.name = name;
        this.age = age;
        this.gender = gender;
    }
    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;
    }
    public String getGender() {
        return gender;
    }
    public void setGender(String gender) {
        this.gender = gender;
    }

    public String toString() {
        return "Student{name = " + name + ", age = " + age + ", gender = " + gender + "}";
    }
}

1.5、反射获取成员方法

Class类中用于获取成员方法的方法

方法名称说明
Method[] getMethods()返回所有公共成员方法对象的数组,包括继承的
Method[] getDeclaredMethods()返回所有成员方法对象的数组,不包括继承的
Method getMethod(String name, Class<?>… parameterTypes)返回单个公共成员方法对象
Method getDeclaredMethod(String name, Class<?>… parameterTypes)返回单个成员方法对象

Method类中用于创建对象的方法

方法名称说明
Object invoke(Object obj, Object… args)运行方法

参数一:用obj对象调用该方法
参数二:调用方法的传递的参数(如果没有就不写)
返回值:方法的返回值(如果没有就不写)

package reflect.Dome4;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;

public class dome {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Class aClass = Class.forName("reflect.Dome4.student");

        //包括父类的方法
        Method[] methods = aClass.getMethods();
        for (Method method : methods) {
            System.out.println(method);
        }
        System.out.println("===================================");
        //不包括父类的方法
        Method[] declaredMethods = aClass.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println(declaredMethod);
        }
        System.out.println("===================================");
        //返回单个公共成员方法变量
        Method getAge = aClass.getMethod("setAge", int.class);
        System.out.println(getAge);
        System.out.println("===================================");
        //返回单个成员方法对象
        Method eat = aClass.getDeclaredMethod("eat", String.class);
        System.out.println(eat);
        //返回方法的名称
        System.out.println("===================================");
        String name = eat.getName();
        System.out.println(name);
        System.out.println("===================================");

        Class<?> declaringClass = eat.getDeclaringClass();
        System.out.println(declaringClass);
        System.out.println("===================================");

        //返回方法里面的参数
        Parameter[] parameters = eat.getParameters();
        for (Parameter parameter : parameters) {
            System.out.println(parameter);
        }
        System.out.println("===================================");
        //返回方法抛出的异常
        Class<?>[] exceptionTypes = eat.getExceptionTypes();
        for (Class<?> exceptionType : exceptionTypes) {
            System.out.println(exceptionType);
        }

        //利用反射运行方法
        student s = new student("xiaowang",23,'男');
        eat.setAccessible(true);
        //没有返回值就不需要写
        //eat.invoke(s, "烧烤");
        //果如有返回值就需要写
        String o = (String) eat.invoke(s, "烧烤");
        System.out.println(o);
    }
}
package reflect.Dome4;

import java.io.IOException;

public class student {
    private String name;
    private int age;
    public char gender;

    public student() {
    }

    public student(String name, int age, char gender) {
        this.name = name;
        this.age = age;
        this.gender = gender;
    }

    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;
    }

    public char getGender() {
        return gender;
    }

    public void setGender(char gender) {
        this.gender = gender;
    }

    private String eat(String str) throws IOException,RuntimeException,ArithmeticException {
        System.out.println(getName()+"正在吃"+str);
        return "奥利给";
    }
    public String toString() {
        return "student{name = " + name + ", age = " + age + ", gender = " + gender + "}";
    }
}

1.6、综合练习

反射的作用:

  1. 获取一个类里面所有的信息,获取到了之后,再执行其他的业务逻辑
  2. 结合配置文件,动态的创建对象并调用方法

1.6.1、保存信息

在这里插入图片描述

package reflect.Dome5;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Field;

public class dome {
    public static void main(String[] args) throws IllegalAccessException, IOException {
        student s = new student("小明",18,181.0,"玩");
        teacher t = new teacher("王老师",30);

        printClass(t);
    }
    public static void printClass(Object obj) throws IllegalAccessException, IOException {
        Class aClass = obj.getClass();
        //创建IO流
        BufferedWriter bw = new BufferedWriter(new FileWriter("D:\\Java\\IDEA\\代码文件\\Three\\a.txt"));

        Field[] declaredFields = aClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            //进行修饰符忽略
            declaredField.setAccessible(true);
            //获取到该变量的名字
            String name = declaredField.getName();
            //获取到该变量的值
            Object value = declaredField.get(obj);
            //写出数据
            bw.write(name+"="+value);
            bw.newLine();
            System.out.println(name+"="+value);
        }
        bw.flush();
        bw.close();
    }
}
package reflect.Dome5;

public class student {
    private String name;
    private int age;
    private double height;
    private String hobby;

    public student() {
    }

    public student(String name, int age, double height, String hobby) {
        this.name = name;
        this.age = age;
        this.height = height;
        this.hobby = hobby;
    }
    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;
    }urn height
     */
    public double getHeight() {
        return height;
    }
    public void setHeight(double height) {
        this.height = height;
    }
    public String getHobby() {
        return hobby;
    }
    public void setHobby(String hobby) {
        this.hobby = hobby;
    }
    public String toString() {
        return "student{name = " + name + ", age = " + age + ", height = " + height + ", hobby = " + hobby + "}";
    }
}
package reflect.Dome5;

public class teacher {
    private String name;
    private int age;
    public teacher() {
    }
    public teacher(String name, int age) {
        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;
    }
    public String toString() {
        return "teacher{name = " + name + ", age = " + age + "}";
    }
}

1.6.2、跟配置文件结合动态创建

在这里插入图片描述

package reflect.Dome6;

import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;

public class dome {
    public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        //读取配置文件中的信息
        Properties prop = new Properties();
        FileInputStream fis = new FileInputStream("prop.properies");
        //读取的文件
        prop.load(fis);
        fis.close();
        System.out.println(prop);

        //获取全类名和方法名
        Object classname = prop.get("classname");
        Object method = prop.get("method");

        System.out.println(classname);
        System.out.println(method);

        //利用反射创建对象并运行方法
        Class<?> aClass = Class.forName((String) classname);
        //获取构造方法
        Constructor con = aClass.getDeclaredConstructor();

        Object o = con.newInstance();
        System.out.println(o);

        //获取成员方法并运行
        Method declaredMethod = aClass.getDeclaredMethod((String) method);
        declaredMethod.setAccessible(true);
        declaredMethod.invoke(o);
    }
}
package reflect.Dome6;

public class student {
    private String name;
    private int age;
    private char gender;

    public student() {
    }

    public student(String name, int age, char gender) {
        this.name = name;
        this.age = age;
        this.gender = gender;
    }
    public void study(){
        System.out.println("正在学习");
    }
    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;
    }
    public char getGender() {
        return gender;
    }
    public void setGender(char gender) {
        this.gender = gender;
    }
    public String toString() {
        return "student{name = " + name + ", age = " + age + ", gender = " + gender + "}";
    }
}
classname=reflect.Dome6.student
method=study

在这里插入图片描述

二、动态代理

2.1、动态代理的思想分析

特点:无侵入式的给代码增加额外的功能

在这里插入图片描述

  • 对象如果嫌身上干的事太多,可以通过代理来转移部分职责
  • 对象有什么方法想被代理,代理就一定要有对应的方法

代理长什么样?
代理里面就是对象要被代理的方法

Java通过什么来保证代理的样子?
通过接口保证,后面的对象和代理需要实现同一个接口接口中就是被代理的所有方法

package dynamicproxy.Dome1;

public class star implements mystar{
    private String name;
    public star() {
    }
    
    public String sing(String name){
        System.out.println(this.name+"唱:"+name);
        return "谢谢大家";
    }
    
    public void dance(String name){
        System.out.println(this.name+"正在跳"+name);
    }
    public star(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String toString() {
        return "star{name = " + name + "}";
    }
}
package dynamicproxy.Dome1;

public interface mystar {
    //把所有想要代理的方法写到接口当中
    public abstract  String sing(String name);
    public abstract void dance(String name);
}

2.2、动态代理的代码实现

java.lang.reflect.Proxy类:提供了为对象产生代理对象的方法︰

public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
参数一:用于指定用哪个类加载器,去加载生成的代理类
参数二:指定接口,这些接口用于指定生成的代理长什么,也就是有哪些方法
参数三:用来指定生成的代理对象要干什么事情
package proxy.Dome1;

public class test {
    public static void main(String[] args) {
        star star = new star("鸡哥");
        mystar proxy = creatProxyUtil.createProxy(star);
        String s = proxy.sing("只因你太美");
        System.out.println(s);

        proxy.dance("鸡你太美");
    }
}
package proxy.Dome1;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class creatProxyUtil {
    public static mystar createProxy(star star){
        // java.lang.reflect.Proxy类:提供了为对象产生代理对象的方法
        mystar mystar = (proxy.Dome1.mystar) Proxy.newProxyInstance(
            //参数一:用于指定那个类加载器,去加载生成的代理类
            creatProxyUtil.class.getClassLoader(),
            //指定接口,这些接口用于指定生成的代理长什么,也就是有哪些方法
            new Class[]{proxy.Dome1.mystar.class},
            //用来指定生成的代理对象要干什么事情
            new InvocationHandler(){
                
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    if ("sing".equals(method.getName())){
                        System.out.println("准备话筒,收钱");
                    } else if ("dance".equals(method.getName())) {
                        System.out.println("准备场地,收钱");
                    }
                    return method.invoke(star,args);
                }
            }
        );
        return mystar;
    };
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值