JAVA面试题总结-反射(57-60)

57.什么是反射?

JAVA反射机制是在运行状态中,对于任意一个类,都能知道这个类的所有属性和方法,对于任意一个对象,都能够调用他的任意方法和属性,这种动态获取的信息以及动态调用对象的方法的功能成为JAVA的反射机制。

58.什么是 java 序列化?什么情况下需要序列化?

序列化是将 Java 对象转换成字节序列的过程。反序列化是将字节序列转换成 Java 对象的过程。

不同进程/程序间进行远程通信时,可以互相发送各种类型的数据,包括文本、图片、音频等,而这些数据都会以二进制序列的形式在网络上传送。

当两个Java进程进行通信时,怎么实现进程间的对象传送呢?

需要使用Java序列化和反序列化,发送方需要把这个Java对象序列化转换成字节序列,在网络上传输,接收方则需要将字节序列反序列化成Java对象。

序列化的好处有哪些呢?

实现了数据的持久化,通过序列化可以把数据永久的保存在硬盘上,实现永久保存对象。

利用序列化实现远程通信,在网络上传输对象。

怎样实现序列化?

只需要将对象实现Serializable接口。

59.动态代理是什么?有哪些应用?

当需要给某个类或者接口中的方法添加一些额外的功能,比如日志、事务的时候,可以通过创建一个代理类来实现这些功能,该代理类既包含了原有类的完整功能,同时在这些功能的基础上添加了其他的逻辑。

动态代理有两种:JDK动态代理和CGLib动态代理。

Spring的核心之一AOP面向切面编程用到的就是基于动态代理实现的。

60.怎么实现动态代理?

动态代理有JDK动态代理和CGLib动态代理。

JDK动态代理只能对实现了接口的类生成代理,而不能针对类,使用的是反射机制,具体实现需要先实现 InvocationHandler 接口,重写invoke()方法,再通过Proxy.newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHander h)创建代理对象,其中被代理对象必须实现接口。

CGLib动态代理则需要添加CGLib的依赖,主要是对指定的类生成一个子类,覆盖其中的方法。

Spring中的AOP面向切面就运用了动态代理,Spring优先使用JDK动态代理,如果没有实现接口,则使用CGLib动态代理,SpringBoot在2.0之前和Spring一样,但在SpringBoot2.0之后优先使用CGLib动态代理,如果需要使用JDK动态代理可以手动配置,在application.properties/yml配置文件中添加字段 spring.aop.proxy-target-class=false即可。

本文代码讲解运用JDK动态代理。

场景:某班级需要收取班费,老师派班长代理老师收取每个人的班费。

首先需要定义一个Person的接口,定义给班费的方法。

package jdkproxytest;
​
/**
*   Person接口
*/
public interface Person {
    //定义给班费的方法
    public void giveMoney();
}

然后创建学生类,实现Person接口,并重写给班费的方法。

package jdkproxytest;
​
/**
*   学生类
*/
public class Student implements Person{
    
    private String name;
    
    public Student(String name) {
        this.name = name;
    }
​
    @Override
    public void giveMoney() {
        System.out.println(name + "上交班费50元");
    }
​
}

然后创建动态代理对象。

package jdkproxytest;
​
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
​
/**
*   代理类 也就是班长 需要实现InvocationHandler
*/
public class ProxyStudent implements InvocationHandler {
    
    private Object object;
    
    //定义获取代理对象的方法
    public Object getProxyStudent(Object object) {
        this.object = object;
        //创建代理对象
        Object proxyObject = Proxy.newProxyInstance(object.getClass().getClassLoader(),object.getClass().getInterfaces() , this);
        return proxyObject;
    }
    
​
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //这里是代理对象对原对象的拓展
        System.out.println("班长收钱");
        Object result = method.invoke(object, args);
        这里是代理对象对原对象的拓展
        System.out.println("班长收完");
        return result;
    }
}
测试:

package jdkproxytest;
​
public class test {
    public static void main(String[] args) {
        ProxyStudent proxyStudent = new ProxyStudent();
        Person person = (Person) proxyStudent.getProxyStudent(new Student("张三"));
        Person person1 = (Person) proxyStudent.getProxyStudent(new Student("李四"));
        person.giveMoney();
        person1.giveMoney();
    }
}
​
执行结果:
班长收钱
李四上交班费50元
班长收完
班长收钱
李四上交班费50元
班长收完

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值