中科星图面试整理
本文最后更新于:2 年前
公司:中科星图股份有限公司
身份:2022届应届生
时间:2022/03/02
中科星图面试整理
Java基础
Java的数据类型
略
&和&&的区别
&:按位与和逻辑与
&&: 短路与
序列化和反序列
定义
Java序列化:把Java对象转换为字节序列的过程
Java反序列化:指把字节序列恢复为Java对象的过程。
作用
序列化作用:
- 在传递和保存对象,保证对象的完整性和可传递性。
- 对象转换为有序字节流,便于在网络上传输或者保存在本地文件中。
反序列化的作用:
根据字节流中保存的对象状态及描述信息,通过反序列化重建对象
==核心作用就是对象状态的保存和重建==
应用(json/xml的数据传递)
在数据传输(也可称为网络传输)前,先通过序列化工具类将Java对象序列化为json/xml文件。
在数据传输(也可称为网络传输)后,再将json/xml文件反序列化为对应语言的对象
优点
- 将对象转为字节流存储到硬盘上,当JVM停机的话,字节流还会在硬盘上默默等待,等待下一次JVM的启动,把序列化的对象,通过反序列化为原来的对象,并且序列化的二进制序列能够减少存储空间(永久性保存对象)。
- 序列化成字节流形式的对象可以进行网络传输(二进制形式),方便了网络传输。
- 通过序列化可以在进程间传递对象。
过程
1、实现序列化的必备要求:
只有实现了==Serializable==或者==Externalizable==接口的类的对象才能被序列化为字节序列。(不是则会抛出异常)
2、JDK中序列化和反序列化的API:
- java.io.ObjectInputStream:对象输入流。
该类的readObject()方法从输入流中读取字节序列,然后将字节序列反序列化为一个对象并返回。
- java.io.ObjectOutputStream:对象输出流。
该类的writeObject(Object obj)方法将将传入的obj对象进行序列化,把得到的字节序列化写入到目标输出流中进行输出
3、三种实现:
- Student类仅仅实现了Serializable接口
ObjectOutputStream采用默认的序列化方式,对Student对象的非transient的实例变量进行序列化。
ObjcetInputStream采用默认的反序列化方式,对Student对象的非transient的实例变量进行反序列化。
- 若Student类仅仅实现了Serializable接口,并且还定义了readObject(ObjectInputStream in)和writeObject(ObjectOutputSteam out),则采用以下方式进行序列化与反序列化。
ObjectOutputStream调用Student对象的writeObject(ObjectOutputStream out)的方法进行序列化。
ObjectInputStream会调用Student对象的readObject(ObjectInputStream in)的方法进行反序列化。
- 若Student类实现了Externalnalizable接口,且Student类必须实现readExternal(ObjectInput in)和writeExternal(ObjectOutput out)方法,则按照以下方式进行序列化与反序列化。
ObjectOutputStream调用Student对象的writeExternal(ObjectOutput out))的方法进行序列化。
ObjectInputStream会调用Student对象的readExternal(ObjectInput in)的方法进行反序列化
Java有很多基础类已经实现了serializable接口,比如String,Vector等
堆和栈的区别
堆是运行时确定内存大小,而栈在编译时即可确定内存大小
理由便是第一节中提到的,这是区分堆和栈的初衷
堆内存由用户管理(Java中由JVM管理),栈内存会被自动释放
栈实现方式采用数据结构中的栈实现,具有(LIFO)的顺序特点,堆为一块一块的内存
栈由于其实现方式,在分配速度上比堆快的多。分配一块栈内存不过是简单的移动一个指针
在JVM中,栈不会被程序员直接使用,程序员操作的一般都是堆。
栈为线程私有而堆为线程共享
类加载器有哪些
classLoader作用就是负责把磁盘上的.class文件 ,加载到JVM内存中,并生成 java.lang.Class类的一个实例。
类加载器大致分成两类
- 系统提供的
- 由 Java 应用开发人员编写的。
系统提供的类加载器主要有下面三个:
(1): 引导类加载器(Bootstrap类加载器)
它是由c++代码实现的,是虚拟机自身的一部分。拿不到他的引用,但实际存在,并且加载一些重要的类,它加载(%JAVA_HOME%\jre\lib),如rt.jar(runtime)、i18n.jar等,这些是Java的核心类。 他是用原生代码来实现的,并不继承自 java.lang.ClassLoader。
(2): 扩展类加载器(Extension类加载器)
虽说能拿到,但是我们在实践中很少用到它,它主要加载扩展目录下的jar包, %JAVA_HOME%\lib\ext
(3): 系统类加载器(System类加载器)
它主要加载我们应用程序中的类,如Test,或者用到的第三方包,如jdbc驱动包等。
理解双亲委派模式
双亲委派模式中的父子关系并非通常所说的类继承关系,而是采用组合关系来复用父类加载器的相关代码。
类加载器收到了类加载请求,它并不会自己先去加载,而是先委托给父类的加载器去执行,如果父类加载器还存在其父类加载器,则进一步向上委托,依次递归,请求最终将到达顶层的启动类加载器,如果父类加载器可以完成类加载任务,就成功返回,倘若父类加载器无法完成此加载任务,子加载器才会尝试自己去加载,这就是双亲委派模式,即每个儿子都很懒,每次有活就丢给父亲去干,直到父亲说这件事我也干不了时,儿子自己想办法去完成。
引用:深入理解Java类加载器(ClassLoader)
优势
- 避免类的重复加载,当父亲已经加载了该类时,就没有必要子ClassLoader再加载一次。
- 安全因素,java核心api中定义类型不会被随意替换,防止核心API库被随意篡改。
List的子类和Map的子类
见博客 Java集合有哪些
HashMap的默认长度
默认HashMap内部数组的长度为16,负载因子为0.75,就是在构造函数里面传的两个值。 阈值就是12(16*0.75=12),这样当第十三个元素加入时,底层数组就会扩容。
JavaWeb
controller的实现过程
标记pojo的注
@Component
AOP的通知
前置通知:在我们执行目标方法之前运行(**@Before**)
后置通知:在我们目标方法运行结束之后,不管有没有异常(**@After**)
返回通知:在我们的目标方法正常返回值后运行(**@AfterReturning**)
异常通知:在我们的目标方法出现异常后运行(**@AfterThrowing**)
环绕通知:目标方法的调用由环绕通知决定,即你可以决定是否调用目标方法,joinPoint.procced()就是执行目标方法的代码 。环绕通知可以控制返回对象(@Around)
多线程
Sleep和Write的区别
sleep是线程类(Thread)的方法,导致此线程暂停执行并指定时间,将执行机会给其他线程,但是监控状态依然保持,到时后会自动恢复。调用sleep不会释放对象锁。
wait是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等待此对象的等待锁定池。只有针对此对象发出==notify
方法(或notifyAll)==后,本线程才进入对象锁定池准备获得对象锁进入运行状态。
多线程的创建方法
- 继承Thread类创建线程类
- 实现Runnable接口创建线程类
- 通过Callable和Future接口创建线程
继承Thread类:
优点:
1、实现起来简单,而且要获取当前线程,无需调用Thread.currentThread()方法,直接使用this即可获取当前线程;
缺点:
1、线程类已经继承Thread类了,就不能再继承其他类;
2、多个线程不能共享同一份资源(如前面分析的成员变量 i );
实现Runnable接口或者Callable接口:
优点(推荐):
1、线程类只是实现了接口,还可以继承其他类;
2、==线程间资源共享==。多个线程可以共用一个target对象,适合多个线程处理同一份资源的情况。
缺点:
1、通过这种方式实现多线程,相较于第一类方式,编程较复杂;
2、要访问当前线程,必须调用Thread.currentThread()方法。
————————————————
参考: JAVA多线程的三种创建方式
run和start的区别
start()能够异步调用run(),直接调用run()只能是同步的,要实现多线程**只能使用 start()**。
用过哪些JUC的方法
MySQL
DML的类型
Like的匹配符
Delete和Dort的区别
事务的特性
隔离等级
SQL执行计划
Linux
常用指令
略
查看日志的指令
参考
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!