JAVA面试题整理大全 (四、反射)

反射

1. 什么是反射?

在运行状态中,都能够查看/调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

主要实现是通过Class类进行动态使用其成员变量、方法和构建对象(java.lang.reflect)

获取Class对象:
  1. Class.forName(“类的全称”)
  2. 类名.class / 实例化对象.getClass()
根据class获取Field(成员变量)对象:
  1. Field getField(name):根据字段名获取某个public的field(包括父类)
  2. Field getDeclaredField(name):根据字段名获取当前类的某个field(不包括父类)
  3. Field[] getFields():获取所有public的field(包括父类)
  4. Field[] getDeclaredFields():获取当前类的所有field(不包括父类)
根据Field 获取设置成员变量值:
  1. filed.get(“实例化对象”) : 获取"实例化对象"的filed字段值
  2. filed.setAccessible(true) :设置访问权限,如果filed为private,则调用get或set时会抛异常 IllegalAccessException,若设置为true不管什么访问限制均可访问
  3. filed.set(“实例化对象”,“值”) : 设置"实例化对象"的filed字段值
根据class获取Method(成员方法)对象:
  1. Method getMethod(name, Class…):获取某个public的Method(包括父类)
  2. Method getDeclaredMethod(name, Class…):获取当前类的某个Method(不包括父类) — 可获取private 方法
  3. Method[] getMethods():获取所有public的Method(包括父类)
  4. Method[] getDeclaredMethods():调用非public方法,我们通过Method.setAccessible(true)允许其调用
根据Method实现成员方法的调用实现:
  1. ‘class类’ invoke(‘实例化对象,静态方法此为null’, Object… ‘方法参数’) 方法调用
  2. getName():返回方法名称
  3. getReturnType():返回方法返回值类型,也是一个Class实例
  4. getParameterTypes():返回方法的参数类型,是一个Class数组
  5. getModifiers():返回方法的修饰符,它是一个int,不同的bit表示不同的含义。
  6. setAccessible(true) : 非public 方法需要
通过Class获取Constructor 构造器
  1. getConstructor(Class…):获取某个public的Constructor;
  2. getDeclaredConstructor(Class…):获取某个Constructor;
  3. getConstructors():获取所有public的Constructor;
  4. getDeclaredConstructors():获取所有Constructor。
通过Constructor 实例对象
  1. newInstance(Object… parameters) :创建一个实例对象
  2. setAccessible(true) : 通过设置来访问非public构造方法。
通过 Class 获取继承关系:
  1. ‘父类Class’ getSuperclass() 获取父类class

2. 什么是 Java 序列化?什么情况下需要序列化?

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

当 Java 对象需要在网络上传输 或者 持久化存储到文件中时,就需要对 Java 对象进行序列化处理。

序列化的实现:类实现 Serializable 接口,这个接口没有需要实现的方法。实现 Serializable 接口是为了告诉 jvm 这个类的对象可以被序列化。

注意事项:

某个类可以被序列化,则其子类也可以被序列化

声明为 static 和 transient 的成员变量,不能被序列化。static 成员变量是描述类级别的属性,transient 表示临时数据

反序列化读取序列化对象的顺序要保持一致

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

没有实现类但是在运行期动态创建了一个接口对象的方式,我们称为动态代码。JDK提供的动态创建接口对象的方式,就叫动态代理(JDK动态代理)。

动态代理实际上有很多应用,比如spring aop的实现,rpc框架的实现,一些第三方工具库的内部使用等等。

Spring AOP的动态代理实现

Spring AOP的动态代理实现主要有两种方式,JDK动态代理和CGLIB字节码生成。
默认情况下,如果Spring AOP发现目标对象后实现了相应的interface,则采用JDK动态代理机制为其生成代理对象。如果没有发现接口,则采用CGLIB的方式为目标对象生成动态的代理对象实例

注: CGLIB 是一种基于ASM的字节码生成库,用于生成和转换Java字节码。 依赖包 cglib
在这里插入图片描述

4. 怎么实现动态代理?

JDK动态代理就是通过反射机制实现的

一. 定义一个InvocationHandler实例,它负责实现接口的方法调用;

二. 通过Proxy.newProxyInstance()创建interface实例,它需要3个参数:

  1. 使用的ClassLoader,通常就是接口类的ClassLoader;
  2. 需要实现的接口数组,至少需要传入一个接口进去;
  3. 用来处理接口方法调用的InvocationHandler实例。

三. 将返回的Object强制转型为接口。

public class Main {
    public static void main(String[] args) {
        InvocationHandler handler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println(method);
                if (method.getName().equals("morning")) {
                    System.out.println("Good morning, " + args[0]);
                }
                return null;
            }
        };
        Hello hello = (Hello) Proxy.newProxyInstance(
            Hello.class.getClassLoader(), // 传入ClassLoader
            new Class[] { Hello.class }, // 传入要实现的接口
            handler); // 传入处理调用方法的InvocationHandler
        hello.morning("Bob");
    }
}

interface Hello {
    void morning(String name);
}


上一章 容器
下一章 对象拷贝

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值