首页 > 编程语言 >Java反射--2021面试题系列教程(附答案解析)--大白话解读--JavaPub版本

Java反射--2021面试题系列教程(附答案解析)--大白话解读--JavaPub版本

时间:2023-05-08 11:08:07浏览次数:41  
标签:面试题 Java -- Object class 对象 序列化 public

> Java反射--2021面试题系列教程(附答案解析)--大白话解读--JavaPub版本

前言

序言

再高大上的框架,也需要扎实的基础才能玩转,高频面试问题更是基础中的高频实战要点。

适合阅读人群

Java 学习者和爱好者,有一定工作经验的技术人,准面试官等。

阅读建议

本教程是系列教程,包含 Java 基础,JVM,容器,多线程,反射,异常,网络,对象拷贝,JavaWeb,设计模式,Spring-Spring MVC,Spring Boot / Spring Cloud,Mybatis / Hibernate,Kafka,RocketMQ,Zookeeper,MySQL,Redis,Elasticsearch,Lucene。订阅不迷路,2021奥利给。

JavaPub知识清单

微信搜:JavaPub,阅读全套系列面试题教程

Java反射--2021面试题系列教程(附答案解析)--大白话解读--JavaPub版本_面试

[toc]

题目

前言

1.什么是反射?

百度百科:

> Java的反射(reflection)机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方法。这种动态获取程序信息以及动态调用对象的功能称为Java语言的反射机制。反射被视为动态语言的关键。

在Java运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意一个对象,能否调用它的任意一个方法

Java反射机制主要提供了以下功能:

  1. 在运行时判断任意一个对象所属的类。
  2. 在运行时构造任意一个类的对象。
  3. 在运行时判断任意一个类所具有的成员变量和方法。
  4. 在运行时调用任意一个对象的方法。

JavaPub参考巨人:https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html

> 到这里如果你对 Java 反射还有一些疑惑,后面再 JavaPub 公众号,还回做更详细的讲解。

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

> 序列化和反序列化是Java中最基础的知识点,也是很容易被大家遗忘的,虽然天天使用它,但并不一定都能清楚的说明白。我相信很多小伙伴们掌握的也就几句概念、关键字(Serializable)而已,如果深究问一下序列化和反序列化是如何实现、使用场景等,就可能不知所措了。在每次我作为面试官,考察Java基础时,通常都会问到序列化、反序列化的知识点,用以衡量其Java基础如何。当被问及Java序列化是什么?反序列化是什么?什么场景下会用到?如果不用它,会出现什么问题等,一般大家回答也就是几句简单的概念而已,有的工作好几年的应聘者甚至连概念都说不清楚,一脸闷逼。

什么是序列化和反序列化

序列化是指将Java对象转换为字节序列的过程,而反序列化则是将字节序列转换为Java对象的过程。

Java对象序列化是将实现了 Serializable 接口的对象转换成一个字节序列,能够通过网络传输、文件存储等方式传输 ,传输过程中却不必担心数据在不同机器、不同环境下发生改变,也不必关心字节的顺序或其他任何细节,并能够在以后将这个字节序列完全恢复为原来的对象(恢复这一过程称之为反序列化)。

对象的序列化是非常有趣的,因为利用它可以实现轻量级持久性,“持久性”意味着一个对象的生存周期不单单取决于程序是否正在运行,它可以生存于程序的调用之间。通过将一个序列化对象写入磁盘,然后在重新调用程序时恢复该对象,从而达到实现对象的持久性的效果。

本质上讲,序列化就是把实体对象状态按照一定的格式写入到有序字节流,反序列化就是从有序字节流重建对象,恢复对象状态。

简单说就是为了保存在内存中的各种对象的状态(也就是实例变量,不是方法),并且可以把保存的对象状态再读出来。虽然你可以用你自己的各种各样的方法来保存object states,但是Java给你提供一种应该比你自己好的保存对象状态的机制,那就是序列化。

什么情况下需要序列化

  1. 当你想把的内存中的对象状态保存到一个文件中或者数据库中时候;
  2. 当你想用套接字在网络上传送对象的时候;
  3. 当你想通过RMI传输对象的时候;

为什么需要使用序列化和反序列化

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

那么当两个Java进程进行通信时,能否实现进程间的对象传送呢?当然是可以的!如何做到呢?这就需要使用Java序列化与反序列化了。发送方需要把这个Java对象转换为字节序列,然后在网络上传输,接收方则需要将字节序列中恢复出Java对象。

我们清楚了为什么需要使用Java序列化和反序列化后,我们很自然地会想到Java序列化有哪些好处:

实现了数据的持久化,通过序列化可以把数据永久地保存到硬盘上(如:存储在文件里),实现永久保存对象。 利用序列化实现远程通信,即:能够在网络上传输对象。


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

动态代理:在运行时,创建目标类,可以调用和扩展目标类的方法。

Java 中实现动态的方式:JDK 中的动态代理 和 Java类库 CGLib。

应用场景如:

  • 统计每个 api 的请求耗时
  • 统一的日志输出
  • 校验被调用的 api 是否已经登录和权限鉴定
  • Spring的 AOP 功能模块就是采用动态代理的机制来实现切面编程

4.怎么实现动态代理?

Java领域中,常用的动态代理实现方式有两种,一种是利用JDK反射机制生成代理,另外一种是使用CGLIB代理。

JDK代理必须要提供接口,而CGLIB则不需要,可以直接代理类。下面分别举例说明。

1.JDK动态代理:

public interface People {
    public void sayHello();
}
public class Chinese implements People {

    @Override
    public void sayHello() {
        System.out.println("Chinese say hello.");
    }
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class PeopleInvocationHandler implements InvocationHandler{
    
    private Object peolple;
    
    Intermediary(Object people){
        this.people = people;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {        Object invoke = method.invoke(people, args);
        System.out.println("-------- end ---------");
        return invoke;
    }
}
import java.lang.reflect.Proxy;

public class Test {
    public static void main(String[] args) {
        People chinese = new People();
        PeopleInvocationHandler invocationHandler = new PeopleInvocationHandler(chinese);
        People proxy = (People) Proxy.newProxyInstance(chinese.getClass().getClassLoader(), chinese.getClass().getInterfaces(), invocationHandler);
        proxy.sayHello();
    }
}

2.CGLIB动态代理

需要引入CGLIB相关Jar包

public class Chinese {
    public void sayHello(){
        System.out.println("Chinese say hello");
    }
}
import java.lang.reflect.Method;

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class ChinesePoxy implements MethodInterceptor {

    @Override
    public Object intercept(Object object, Method method, Object[] args,MethodProxy methodProxy) throws Throwable {
        Object intercept = methodProxy.invokeSuper(object, args);
     System.out.println("-------- end ---------");
    return intercept; 
  } 
}
import net.sf.cglib.proxy.Enhancer;

public class Test {
    public static void main(String[] args) {
        ChineseProxy chineseProxy = new ChineseProxy();
        
        Enhancer enhancer = new Enhancer();  
        enhancer.setSuperclass(Chinese.class);
        enhancer.setCallback(chineseProxy);
        
        Chinese proxy = (Chinese) enhancer.create();
        proxy.sayHello();
    }
}


如何使用Java的反射?

  • 通过一个全限类名创建一个对象
  1. Class.forName(“全限类名”); 例如:com.mysql.jdbc.Driver Driver类已经被加载到 jvm中,并且完成了类的初始化工作就行了
  2. 类名.class; 获取Class<?> clz 对象
  3. 对象.getClass();
  • 获取构造器对象,通过构造器new出一个对象
  1. Clazz.getConstructor([String.class]);
  2. Con.newInstance([参数]);
  • 通过class对象创建一个实例对象(就相当与new类名()无参构造器)
  1. Cls.newInstance();
  • 通过class对象获得一个属性对象
  1. Field c=cls.getFields():获得某个类的所有的公共(public)的字段,包括父类中的字段。
  2. Field c=cls.getDeclaredFields():获得某个类的所有声明的字段,即包括public、private和proteced,但是不包括父类的声明字段
  • 通过class对象获得一个方法对象
  1. Cls.getMethod(“方法名”,class……parameaType);(只能获取公共的)
  2. Cls.getDeclareMethod(“方法名”);(获取任意修饰的方法,不能执行私有)
  3. M.setAccessible(true);(让私有的方法可以执行)
  • 让方法执行
  1. Method.invoke(obj实例对象,obj可变参数);-----(是有返回值的)

2021 面试题,认准 JavaPub。

标签:面试题,Java,--,Object,class,对象,序列化,public
From: https://blog.51cto.com/wangshiyu/6253132

相关文章

  • 京东小程序折叠屏适配探索 | 京东云技术团队
    前言随着近年来手机行业的飞速发展,手机从功能机进入到智能机,手机屏幕占比也随着技术和系统的进步越来越大,特别是Android10推出以后,折叠屏逐渐成为Android手机发展的趋势。图1Android手机屏幕发展趋势京东小程序近年来也支持了越来越多的业务和应用,做好小程序的折叠屏的适配也是......
  • 如何决定使用 HashMap 还是 TreeMap?
    @[toc]问:如何决定使用HashMap还是TreeMap?介绍TreeMap<k,v>的Key值是要求实现java.lang.Comparable,所以迭代的时候TreeMap默认是按照Key值升序排序的;TreeMap的实现是基于红黑树结构。适用于按自然顺序或自定义顺序遍历键(key)。HashMap<k,v>的Key值实现散列hashCode(),分布是散列的......
  • git出现异常处理
    这个教程,错过了,就错过了,各位!!!@[toc]前言有时候,公司提交的代码必须使用公司邮箱,而你误操作,直接把自己个人邮箱提交上去了,此时你就会遇到这样的需求:如何修改git已提交的邮箱?(因为有些公司是不允许使用个人邮箱提交代码)异常master分支合并到develop分支,执行gitpush操作时。remote:......
  • ZK----第七章 ZUML页面及XUL组件集
    基本组件Label组件:89用来显示一段文字<labelvalue=”hello”/>属性:pre、hyphen、maxlength、multiline  按钮组件:90两种:button和toolbarbutton属性: Label:名称、image:按钮显示的图像、(dir:控制label和image的显示位置,orient:控制布局为横向或纵向)<button label=”left”ima......
  • 在cmd中运行javac编译java文件报错: 编码GBK的不可映射字符、 非法字符: \65279
    操作背景:我在eclipse建立了个HelloWorld.java文件,格式UTF-8,然后复制保存到C:\Users\alex\test目录下,在此处运行按住Shift+右键调出cmd命令窗口,输入命令:javac HelloWorld.java,然后报错:HelloWorld.java:6:错误:编码GBK的不可映射字符解决办法:方法一:带上编码utf-8,运行命令:javac-e......
  • 了解Redis过期策略及实现原理
    大约阅读4分钟如果你使用过redis,那你一定知道过期策略这个命令吧,如果让你设计一个过期键接口,你有什么想法?我们在使用redis时,一般会设置一个过期时间,当然也有不设置过期时间的,也就是永久不过期。当我们设置了过期时间,redis是如何判断是否过期,以及根据什么策略来进行删除的。redi......
  • volatile关键字的作用
    大约阅读3分钟引言:以前只是看过介绍volatile的文章,对其的理解也只是停留在理论的层面上,由于最近在项目当中用到了关于并发方面的技术,所以下定决心深入研究一下java并发方面的知识。网上关于volatile的文章非常多,但是并没有讲解非常详细的文章。(哪位要是有好的资料麻烦共享一份给......
  • elasticsearch7.x 插件安装异常
     (本博客近期所有es文章都是基于elasticsearch7.1.0),请选择Plugin[analysis-pinyin]wasbuiltforElasticsearchversion7.1.1butversin明显是版本号不一致,解决:进入vimelasticsearch-7.1.0/plugins/pinyin/plugin-descriptor.properties修改为elasticsearch对应版本,重新启动E......
  • 多通道振弦传感器无线采集仪蓝牙功能的使用
    多通道振弦传感器无线采集仪蓝牙功能的使用无线采集仪内置了蓝牙通讯功能,制式为ISMBandV5.1BLE。可以使用无线采集仪支持的通讯协议经由蓝牙接口完成无线采集仪访问(参数读取、设置,实时数据获取等)。配对码为0000或者1234。以手机为例说明。(1)下载并安装APP在任意的手......
  • (非root权限)java环境配置
     打开文件:vim~/.bashrc 末尾添加配置:exportJAVA_HOME=/usr/share/jdk8exportPATH=$JAVA_HOME/bin:$PATHexportCLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar更新:source~/.bashrc(更新路径) ......