CommonCollection1反序列化链学习

Python微信订餐小程序课程视频

https://edu.csdn.net/course/detail/36074

Python实战量化交易理财系统

https://edu.csdn.net/course/detail/35475

CommonsCollection1

1、前置知识

1.1、反射基础知识
1.1.1、 对象与类的基础知识
类(class),对象(object)
对象是类的实例化,中华田园犬(object)是狗(class)的实例化
类是对象的抽象化,狗(class)是中华田园犬(object)抽象化

1.1.2、反射获取对象过程

1、我们可以通过以下三种方法获取Class对象类型

Class classType = String.class;
Class classType = new String().getClass();/*new String()是一个对象*/
Class classType = Class.forName("java.lang.String");

2、在Class类中包含着很多方法函数,其中在本章节使用最频繁的就是

getName():获得类的完整名字。 
getFields():获得类的public类型的属性。

getDeclaredFields():获得类的所有属性。

getMethods():获得类的public类型的方法。

getDeclaredMethods():获得类的所有方法。

getMethod(String name, Class[] parameterTypes):获得类的特定方法,name参数指定方法的名字,parameterTypes参数指定方法的参数类型。

getConstrutors():获得类的public类型的构造方法。

getConstrutor(Class[] parameterTypes):获得类的特定构造方法,parameterTypes参数指定构造方法的参数类型。

newInstance():通过类的不带参数的构造方法创建这个类的一个对象。

2、通过默认构造方法创建一个新的对象,即先调用Class类的getConstructor()方法获得一个Constructor对象,它代表默认的构造方法,然后调用Constructor对象的newInstance()方法构造一个实例。(此处new Class[]{}、new Object[]{}表示空参数,既调用默认的无参数的构造方法)

Object objectCopy=classType.getConstructor(new Class[]{}).newInstance(new Object[]{});

3、获得对象的所有属性,即通过Class类的getDeclaredFields()方法返回类的所有属性,包括public、protected、default和private访问级别的属性

Field fields[]=classType.getDeclaredFields();

4、获得每个属性相应的get/set方法,然后执行这些方法,把原来的对象属性拷贝到新的对象中。

这里我们可以写一个InvokeTester的类,然后运用反射机制调用一个InvokeTester对象的add()方法(自定义方法),如add()方法的两个参数为int类型,那么获取表示add()方法的Method对象代码如下:

Method addMethod=classType.getMethod("add",new Class[]{int.class,int.class});

5、反射调用addMethod方法

//获得和属性对应的getXXX()方法
Method getMethod=classType.getMethod(getMethodName,new Class[]{});
//获得和属性对应的setXXX()方法
Method setMethod=classType.getMethod(setMethodName,new Class[]{field.getType()});
//具体实施(第四点描述)
Method addMethod=classType.getMethod("add",new Class[]{int.class,int.class});

//调用原对象的getXXX()方法
Object value=getMethod.invoke(object,new Object[]{});
System.out.println(fieldName+":"+value);
//调用拷贝对象的setXXX()方法
setMethod.invoke(objectCopy,new Object[]{value});
addMethod.invoke()

6、具体一个小例子

首先有个Users类,他有属性名字(name)、年龄(age)和会算加法()

public class Users {
    String name;
    int 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 int add(int num1, int num2){
        int addnum= num1+num2;
        return addnum;

    }

}

那么我们反射获取他的某一个user对象的名字、年龄和加法

第一反射获取多参数的方法add

import java.lang.reflect.Method;

public class Test {
    public static void main(String[] args) throws Exception {
        //反射获取类对象类型,这里获取的是Users类对象类型
        Class users = Class.forName("Users");
        //类对象类型实例化,,即先调用Class类的getConstructor()方法获得一个Constructor对象,它代表默认的构造方法,然后调用Constructor对象的newInstance()方法构造一个实例。(此处new Class[]{}、new Object[]{}表示空参数,既调用默认的无参数的构造方法)
        Object user = users.getConstructor(new Class[]{}).newInstance(new Object[]{});
        //反射获取指定的类对象类型的add方法,add方法需要两个参数,参数类型为int型,getMethod类型的第二个参数必须是Class对象类型
        Method add = users.getMethod("add", new Class[]{int.class, int.class});
        //add方法反射调用(invoke)user对象,并且传入add方法的俩个参数值,invoke方法的参数必须是object对象
        Object num = add.invoke(user, new Object[]{1, 2});
        System.out.println((Integer) num);


    }
}


反射调用单参数的方法setName和无参数方法getName

import java.lang.reflect.Method;

public class Test {
    public static void main(String[] args) throws Exception {
/*
 //反射获取类对象类型,这里获取的是Users类对象类型
 Class users = Class.forName("Users");
 //类对象类型实例化,,即先调用Class类的getConstructor()方法获得一个Constructor对象,它代表默认的构造方法,然后调用Constructor对象的newInstance()方法构造一个实例。(此处new Class[]{}、new Object[]{}表示空参数,既调用默认的无参数的构造方法)
 Object user = users.getConstructor(new Class[]{}).newInstance(new Object[]{});
 //反射获取指定的类对象类型的add方法,add方法需要两个参数,参数类型为int型,getMethod类型的第二个参数必须是Class对象类型
 Method add = users.getMethod("add", new Class[]{int.class, int.class});
 //add方法反射调用(invoke)user对象,并且传入add方法的俩个参数值,invoke方法的参数必须是object对象
 Object num = add.invoke(user, new Object[]{1, 2});
 System.out.println((Integer) num);

*/

        Class users = Class.forName("Users");
        Object zhangsan = users.getConstructor(new Class[]{}).newInstance(new Object[]{});
        //反射获取Users类的setName()方法 ,需要传入setName的所需的参数类型,此处为String.class类型
        Method setName = users.getMethod("setName", new Class[]{String.class});
        //反射设置zhangsan对象实例的名字为张三
        setName.invoke(zhangsan,new Object[]{"张三"});
        //反射获取Users类的getName()方法,需要传入getName的参数类型,此处为空
        Method getName = users.getMethod("getName", new Class[]{});
        //反射获取zhangsan对象实例的名字
        Object Name = getName.invoke(zhangsan);
        System.out.println((String) Name);


    }
}


1.1.3、反射的基本用法

反射又有很多琐碎的点,这里只讲它的基本用法如果当前拥有一个对象的话,那么可以动态的调用该对象的所有方法

// Step1 获取Class对象
Class cls = obj.getClass();
// Step2 获取想要的方法对象
Method mth = cls.getMethod("MethodName",new Class[]{arg1_type,arg2_type});    
// Step3 调用方法
mth.invoke(obj,new Object[]{arg1,arg2})

这里注意的是getMethod的第二个参数为Class数组,Class的概念我们之前也提到过。

1.2、动态代理知识

动态代理需要理解反射包的三个类

反射包 java.lang.reflect 的三个类:InvocationHandler,Method,Proxy

InvocationHandler

这个类其实就一个方法就是invoke方法,该方法用代理商在不改变代理对象的情况,需要添加的功能

参数:

Object proxy:jdk的代理类,无需赋值

Method method:代理对象的方法,jdk提供的Method的对象

Object[] args:代理对象的方法执行的参数

package java.lang.reflect;

public interface InvocationHandler {

    public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable;
}


Method

Method方法主要在InvocationHandler的invoke方法中实现,表示执行代理对象的方法

Method.invoke(目标的对象,方法的参数)

image-20220326234845996

Proxy

newProxyInstance的方法的三个参数为

ClassLoader loader:类加载器,负责向内存中加载对象的。使用反射获取的

Class [] interfaces :目标对象实现的接口,也是反射获取的

InvocationHandler h:我们自己写的,代理需要完成的功能

image-20220326235224217

举个具体里的例子(Usb)

首先实现一个统一的买usb的接口,里面有一个卖usb的方法

public interface Usbsell {
    float sell(int acount);
}

金士顿厂家要卖usb,所以继承这个接口,他买85元

package com.akkacloud.factory;

import com.akkacloud.service.Usbsell;

public class UsbKingFactor implements Usbsell {

    @Override
    public float sell(int acount) {
        return 85.0f;
    }
}

我们是一个商店,去买我们要赚差价

第一种写法,直接在主函数中创建我们的InvocationHandler接口

package com.akkacloud;

import com.akkacloud.factory.UsbKingFactor;
import com.akkacloud.handler.MysellHandler;
import com.akkacloud.service.Usbsell;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.refl
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值