java反射简单案例

java反射

动态代理

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

为什么需要动态代理?调用者->代理->接口->对象

代理是什么样的?代理的方法就是对象被代理的方法

如何保证代理?接口对象和代理需要实现同一个接口,接口中的方法就是对象被代理的所有方法

QQSpeed-demo

接口

public interface Car {
    // 代理和对象都要实现run方法,对象所有需要被代理的方法都要在接口中定义
    public void run(String roadName);
}

对象类

public class Porsche implements Car {
    private String carName;

    public Porsche() {}

    public Porsche(String carName) { this.carName = carName; }

    // Porsche只保留run方法
    @Override
    public void run(String roadName) {
        System.out.println(this.carName + " is running on the " + roadName);
    }

    public String getCarName() { return carName; }

    public void setCarName(String carName) { this.carName = carName; }

    public String toString() { return "porsche{carName = " + carName + "}"; }

}

代理类

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

public class ProxyUtil {
    // 创建代理
    public  static Car creatProxy(Porsche porsche){
        Car car = (Car) Proxy.newProxyInstance(
                ProxyUtil.class.getClassLoader(), // 类加载器
                new Class[]{Car.class}, // 接口
                new InvocationHandler() { // 代理要做的事情
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        if("run".equals(method.getName())){
                            // 加入赛前的准备机制
                            System.out.println("Reno joins the game room");
                            System.out.println("Ferrari joins the game room");
                            System.out.println("Maserati joins the game room");
                            System.out.println("All vehicles are ready");
                            System.out.println("Countdown three two one");
                            System.out.println("QQSpeed start");
                            // 调用Porsche保留的run方法
                            method.invoke(porsche,args);
                            // 加入赛后庆祝机制
                            System.out.println(porsche.getCarName() + " win the first!!!");
                        }
                        return null;
                    }
                }
        );
        return car;
    }
}

测试类

public class testRun {
    public static void main(String[] args) {
        // 创建对象 porsche-911
        Porsche porsche = new Porsche("porsche-911");
        // 创建porsche-911的代理
        Car proxy = ProxyUtil.creatProxy(porsche);
        // 通过代理执行porsche-911的方法,以及代理的一些职能
        proxy.run("Mountain Haruna");
    }
}

运行结果

Reno joins the game room
Ferrari joins the game room
Maserati joins the game room
All vehicles are ready
Countdown three two one
QQSpeed start
porsche-911 is running on the Mountain Haruna
porsche-911 win the first!!!

反射

什么是反射?反射允许对封装的字段、方法和构造函数的信息进行编程访问

idea的代码提示就是反射实现的

第一步、获取到类

.class字节码文件而不是.java文件

获取class对象的三种方式
// 1.源代码阶段 代码并未加载到内存当中,依旧是硬盘中的操作
Class.forName("全类名");
// 2.加载阶段 将.class文件加载到内存中
类名.class
// 3.运行阶段 
对象.getClass()
demo

被获取类

package stepOne;
// 雷诺
public class Reno {
    // 直线最高时速
    private String straightTopSpeed;
    // 0 - 180km/h加速用时
    private String AccelerationTime0f180;
    // 车身重量 1680 千克
    private String BodyWeight;
    // 高速转弯半径
    private String HighSpeedTurningRadius;

    public Reno() {
    }

    public Reno(String straightTopSpeed, String AccelerationTime0f180, String BodyWeight, String HighSpeedTurningRadius) {
        this.straightTopSpeed = straightTopSpeed;
        this.AccelerationTime0f180 = AccelerationTime0f180;
        this.BodyWeight = BodyWeight;
        this.HighSpeedTurningRadius = HighSpeedTurningRadius;
    }

    public String getStraightTopSpeed() { return straightTopSpeed; }

    public void setStraightTopSpeed(String straightTopSpeed) { this.straightTopSpeed = straightTopSpeed; }

    public String getAccelerationTime0f180() { return AccelerationTime0f180; }

    public void setAccelerationTime0f180(String AccelerationTime0f180) { this.AccelerationTime0f180 = AccelerationTime0f180; }

    public String getBodyWeight() { return BodyWeight; }

    public void setBodyWeight(String BodyWeight) { this.BodyWeight = BodyWeight; }

    public String getHighSpeedTurningRadius() { return HighSpeedTurningRadius; }

    public void setHighSpeedTurningRadius(String HighSpeedTurningRadius) { this.HighSpeedTurningRadius = HighSpeedTurningRadius; }

    public String toString() {
        return "Reno{straightTopSpeed = " + straightTopSpeed + ", AccelerationTime0f180 = " + AccelerationTime0f180 + ", BodyWeight = " + BodyWeight + ", HighSpeedTurningRadius = " + HighSpeedTurningRadius + "}";
    }
}

测试类

package stepOne;

public class getClass {
    public static void main(String[] args) throws ClassNotFoundException {
        // 1.源代码阶段  代码并未加载到内存当中,依旧是硬盘中的操作  Class.forName("全类名") 最为常用
        Class clazz1 = Class.forName("stepOne.Reno");
        // 2.加载阶段  将.class文件加载到内存中  类名.class 一般当参数进行传递
        Class clazz2 = Reno.class;
        // 3.运行阶段  对象.getClass()  只有拥有这个类的对象时才可以使用
        Reno reno = new Reno();
        Class clazz3 = reno.getClass();

        System.out.println(clazz1==clazz2&&clazz2==clazz3);
    }
}

第二步、使用类的信息

从.class文件获取类的字段、方法、构造函数

初始化类User
package stepTwo;

import java.io.IOException;

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

    public String sleep(){
        return "im sleeping";
    }

    private void eat(String food) throws IOException, NullPointerException, ClassCastException {
        System.out.println("eat" + food);
    }

    public User() {
    }
    public User(String name){
        this.name = name;
    }

    protected User(int age){
        this.age = age;
    }

    private User(String name, int age){
        this.name = name;
        this.age = age;
    }

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

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

    /**
     * 获取
     * @return gender
     */
    public String getGender() {
        return gender;
    }

    /**
     * 设置
     * @param gender
     */
    public void setGender(String gender) {
        this.gender = gender;
    }

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

获取构造函数

Constructor类用来描述构造函数,Constructor类的对象就是构造函数的对象

package stepTwo;

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

public class getConstructor {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class clazz = Class.forName("stepTwo.User");
        // 获取构造函数的四种方式
        // 1.返回单个公共构造方法对象
        Constructor con = clazz.getConstructor(String.class);
        System.out.println(con);

        // 2.返回所有公共构造方法对象的数组
        Constructor[] cons = clazz.getConstructors();
        for(Constructor c : cons) {
            System.out.println(c);
        }

        // 3.返回单个构造方法对象
        Constructor dcon = clazz.getDeclaredConstructor(String.class, int.class);
        System.out.println(dcon);

        // 4.返回所有构造方法对象的数组
        Constructor[] dcons = clazz.getDeclaredConstructors();
        for(Constructor dc : dcons){
            System.out.println(dc);
        }

        // 获取构造函数详细信息,以方法3为例
        // 1.获取参数个数
        int mod = dcon.getModifiers();
        System.out.println(mod);
        // 2.获取参数
        Parameter[] parameters = dcon.getParameters();
        for(Parameter p : parameters){
            System.out.println(p);
        }
        // 3.创建对象
        // 暴力反射:临时取消权限校验
        dcon.setAccessible(true);
        User user = (User) dcon.newInstance("zhangsan", 25);
        System.out.println(user);

    }

}
获取成员变量

Field类用来描述成员变量,Field类的对象就是成员变量的对象

package stepTwo;

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

public class getField {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
        Class clazz = Class.forName("stepTwo.User");
        // 获取成员变量的四种方式
        // 1.返回单个公共成员变量对象
        Field gender = clazz.getField("gender");
        System.out.println(gender);

        // 2.返回所有公共成员变量对象的数组
        Field[] fields = clazz.getFields();
        for(Field f : fields) {
            System.out.println(f);
        }

        // 3.返回单个成员变量对象
        Field age = clazz.getDeclaredField("age");
        System.out.println(age);

        // 4.返回所有成员变量对象的数组
        Field[] dfields = clazz.getDeclaredFields();
        for(Field df : dfields){
            System.out.println(df);
        }

        // 获取成员变量详细信息,以方法3为例
        // 1.获取权限修饰符
        int modi = age.getModifiers();
        System.out.println(modi);

        // 2.获取成员变量名
        String n = age.getName();
        System.out.println(n);

        // 3.获取成员变量数据类型
        Class type = age.getType();
        System.out.println(type);

        // 4.获取成员变量记录的值
        User user = new User("zhangsan", 25, "♂");
        age.setAccessible(true);
        int value = (int) age.get(user);
        System.out.println(value);

        // 5.修改对象的成员变量值
        age.set(user, 22);
        System.out.println(user);

    }

}
获取成员方法

Method类用来描述成员方法,Method类的对象就是成员方法的对象

package stepTwo;

import java.lang.reflect.*;

public class getMethod {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Class clazz = Class.forName("stepTwo.User");
        // 获取成员变量的四种方式
        // 1.返回单个公共成员方法对象
        Method sleep = clazz.getMethod("sleep", null);
        System.out.println(sleep);

        // 2.返回所有公共成员方法对象的数组(包含父类中所有的公共方法)
        Method[] methods = clazz.getMethods();
        for(Method m : methods) {
            System.out.println(m);
        }

        // 3.返回单个成员方法对象
        Method eat = clazz.getDeclaredMethod("eat", String.class);
        System.out.println(eat);

        // 4.返回所有成员方法对象的数组(不包含父类中的方法,但包含本类中的所有方法,包括私有方法)
        Method[] dmethods = clazz.getDeclaredMethods();
        for(Method dm : dmethods){
            System.out.println(dm);
        }

        // 获取成员方法详细信息,以方法3为例
        // 1.获取权限修饰符
        int modi = eat.getModifiers();
        System.out.println(modi);

        // 2.获取成员方法名
        String n = eat.getName();
        System.out.println(n);

        // 3.获取成员方法形参
        Parameter[] parameters = eat.getParameters();
        for(Parameter parameter : parameters){
            System.out.println(parameter);
        }

        // 4.获取成员方法抛出的异常
        Class[] exceptionTypes = eat.getExceptionTypes();
        for(Class exceptionType : exceptionTypes){
            System.out.println(exceptionType);
        }

        // 5.运行方法
        User u = new User();
        eat.setAccessible(true);
        eat.invoke(u, " potato floss");

        // 6.获取方法运行结果
        String result = (String) sleep.invoke(u);
        System.out.println(result);
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值