java面试题(反射、对象拷贝)

点赞关注+收藏,万分感谢!!

1、什么是反射?

反射是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;

这种动态获取的信息以及动态调用对象的方法的功能称为 Java 语言的反射机制。

工作原理:当一个字节码文件加载到内存的时候, jvm会对该字节码进行解剖,然后创建一个对象的Class对象,jvm把字节码文件的信息全部都存储到该Class对象中,

我们只要获取到Class对象,我们就可以使用该对象设置对象的属性或者调用对象的方法等操作。

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

Java 序列化是为了保存各种对象在内存中的状态,并且可以把保存的对象状态再读出来。

以下情况需要使用 Java 序列化:

想把的内存中的对象状态保存到一个文件中或者数据库中时候;

想用套接字在网络上传送对象的时候;

想通过RMI(远程方法调用)传输对象的时候。

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

动态代理是运行时动态生成代理类。

动态代理的应用有 spring aop、hibernate 数据查询、测试框架的后端 mock、rpc,Java注解对象获取等。

4、怎么实现动态代理?

JDK 原生动态代理和 cglib 动态代理。JDK 原生动态代理是基于接口实现的,而 cglib 是基于继承当前类的子类实现的。

比较:

jdk动态代理是由java内部的反射机制来实现的,cglib动态代理底层则是借助asm来实现的。反射机制在生成类的过程中比较高效,而asm在生成类之后的相关执行过程中比较高效(可以通过将asm生成的类进行缓存,这样解决asm生成类过程低效问题)。

jdk动态代理的应用前提是目标类必须基于统一的接口。因此,jdk动态代理有一定的局限性,cglib这种第三方类库实现的动态代理应用更加广泛,且在效率上更有优势。

CGLIB 和 JDK 动态代理之间的区别:

JDK 动态代理只能对接口进行代理,不能对普通的类进行代理,这是因为 JDK 动态代理生成的代理类,其父类是 Proxy,且 Java 不支持类的多继承。

CGLIB 能够代理接口和普通的类,但是被代理的类不能被 final 修饰,且接口中的方法不能使用 final 修饰。

JDK 动态代理使用 Java 反射技术进行操作,在生成类上更高效。

CGLIB 使用 ASM 框架直接对字节码进行修改,使用了 FastClass 的特性。在某些情况下,类的方法执行会比较高效。

PS:

静态代理:一个接口,接口中定义相应(代理对象和目标对象都要实现)的 方法。静态代理缺点:不灵活,重复代码多。

基于接口代理(jdk)

原理过程:

调用Proxy.newProxyInstance生成代理类的实现类;

调用getProxyClass0寻找或生成指定代理类;

(从缓存中取,如果没有,就生成一个放在缓存中 : 通过ProxyClassFactory生成);

缓存调用ProxyClassFactory生成代理类,proxy class的生成最终调用ProxyClassFactory的apply方法;

生成字节码之后利用反射生成实例:   Proxy.newProxyInstance 创建的代理对象是在jvm运行时动态生成的一个对象,

它并不是我们的InvocationHandler类型,也不是我们定义的那组接口的类型,而是在运行是动态生成的一个对象,并且命名方式都是这样的形式,以$开头,proxy为中,最后一个数字表示对象的标号。

InvocationHandler接口:

每一个动态代理类都必须要实现InvocationHandler这个接口,并且每个代理类的实例都关联到了一个handler,当我们通过代理对象调用一个方法的时候,

这个方法的调用就会被转发为由InvocationHandler这个接口的 invoke 方法来进行调用。

Proxy类

Proxy这个类的作用就是用来动态创建一个代理对象的类,它提供了许多的方法,但是我们用的最多的就是 newProxyInstance 这个方法:

这个方法的作用就是得到一个动态的代理对象。

基于继承代理(cglib)

CGLIB 通过动态生成一个需要被代理类的子类(即被代理类作为父类),该子类重写被代理类的所有不是 final 修饰的方法,并在子类中采用方法拦截的技术拦截父类所有的方法调用,进而织入横切逻辑。此外,因为 CGLIB 采用整型变量建立了方法索引,这比使用 JDK 动态代理更快(使用 Java 反射技术创建代理类的实例)。

  在底层实现上,CGLIB 使用字节码处理框架 ASM,该框架用于转换字节码并生成新的类。但是不鼓励直接使用 ASM,因为它要求对于 JVM 的内部结构包括 class 文件的格式和 JVM 指令都很熟悉,若一旦出现错误,会导致 JVM 崩溃级别的异常。

Java字节码生成开源框架–ASM:

ASM 是一个 Java 字节码操控框架。它能够以二进制形式修改已有类或者动态生成类。ASM 可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为。ASM 从类文件中读入信息后,能够改变类行为,分析类信息,甚至能够根据用户要求生成新类。

不过ASM在创建class字节码的过程中,操纵的级别是底层JVM的汇编指令级别,这要求ASM使用者要对class组织结构和JVM汇编指令有一定的了解。

5、反射的应用?

Java的反射机制在实际项目中应用广泛,常见的应用场景有:

使用JDBC时,如果要创建数据库的连接,则需要先通过反射机制加载数据库的驱动程序 ;

多数框架都支持注解/XML配置,从配置中解析出来的类是字符串,需要利用反射机制实例化;

面向切面编程(AOP)的实现方案,是在程序运行时创建目标对象的代理类,这必须由反射机制来实现。

6、为什么需要反射?

通过反射机制,我们可以实现如下的操作:

程序运行时,可以通过反射获得任意一个类的Class对象,并通过这个对象查看这个类的信息;

程序运行时,可以通过反射创建任意一个类的实例,并访问该实例的成员;

程序运行时,可以通过反射机制生成一个类的动态代理类或动态代理对象。

7、获取Class类对象有三种方式?

类名.class属性

对象名.getClass()方法

Class.forName(全类名)方法

对象拷贝

1、为什么要使用克隆?

克隆的对象可能包含一些已经修改过的属性,而 new 出来的对象的属性都还是初始化时候的值,所以当需要一个新的对象来保存当前对象的“状态”就靠克隆方法了。

2、如何实现对象克隆?

实现 Cloneable 接口并重写 Object 类中的 clone() 方法。

实现 Serializable 接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆。

3、深拷贝和浅拷贝区别是什么?

浅克隆:当对象被复制时只复制它本身和其中包含的值类型的成员变量,而引用类型的成员对象并没有复制。

深克隆:除了对象本身被复制外,对象所包含的所有成员变量也将复制。

  • 12
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值