1. 如何理解对象的浅拷贝和深拷贝?
在Java语言里,当我们需要拷贝一个对象时,有两种类型的拷贝:浅拷贝与深拷贝。
浅拷贝只是拷贝了源对象的地址,所以源对象的值发生变化时,拷贝对象的值也会发生变化。
深拷贝则是拷贝了源对象的所有值,所以即使源对象的值发生变化时,拷贝对象的值也不会改变。深拷贝常用方案中可以基于Java中的Cloneable接口或者采用序列化和反序列化方案进行实现。
~~~
2. 描述内存溢出和内存泄漏的区别?
定义:
内存泄漏:分配出去的内存无法回收,造成的现象叫做内存泄漏。
内存溢出:内存中剩余的内存不足以分配给新的内存请求就会内存溢出。
关系:内存泄漏累积到一定程度,会造成内存溢出。
内存溢出并不一定是由内存泄漏引起的,还可能是因为创建了过大的对象。
OOM:OutOfMemoryError
3. 描述一下Java中的四大引用数据类型?
强引用
通过对象自身类型或父类类型直接引用当前对象称之为强引用,使用"强引用"引用的对象,即便JVM内存空间不足,触发了GC操作,JVM宁愿抛出OutOfMemoryError运行时错误,也不会回收有强引用引用的对象。
软引用
通过SoftReference类型对象实现。"软引用"引用的对象,在JVM认为内存不足时,会去试图回收其引用的对象。即JVM 会确保在抛出 OutOfMemoryError 之前,清理软引用指向的对象。软引用可以和一个引用队列(ReferenceQueue)联合使用,如果“软引用”所引用的对象被垃圾回收器回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。后续,我们可以调用ReferenceQueue的poll()方法来检查是否有它所关心的对象被回收。
弱引用
通过WeakReference类实现。当GC时,一旦发现了具有“弱引用”引用的对象,不管当前内存空间足够与否,都可能会回收它的内存。由于垃圾回收器是一个优先级很低的线程,因此不一定会很快回收弱引用的对象。弱引用也可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。
虚引用
也叫幻象引用,通过PhantomReference类对象来实现。无法通过虚引用访问对象的任何属性或函数。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。虚引用必须和引用队列 (ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。
4. 描述一下Java中的反射以及有什么优势和劣势?
~~~
反射机制实际上就是上帝模式,如果说直接方法的调用是 Java 的默认业务执行方式,那反射机制就是上帝偷偷开的后门,只要存在对应的class,一切都能够被调用。那上帝为什么要打开这个后门呢?这涉及到了静态和动态的概念。静态编译一般指在编译时确定类型,绑定对象。动态编译则是在运行时确定类型,绑定对象。两者的区别在于,动态编译可以最大程度地支持多态,而多态最大的意义在于降低类的耦合性,因此反射的优点就很明显了,解耦以及提高代码的灵活性。其劣势主要是性能瓶颈,反射相当于一系列解释操作,通知 JVM 要做的事情,性能比直接的java操作要慢很多。
反射在我们平时项目的业务开发过程中很少用到,但这不能说明反射机制没有用,实际上有很多框架(mybatis,spring)、中间件(tomcat)的开发,还有一些灵活的工具类都会用到反射。
5. 描述一下你对Synchronized关键字的理解?
~~~
Synchronized是Java中解决并发安全问题的一种最常用的方法,也是最简单的一种方法。其主要作用主要包括如下三个方面:
1)确保并发线程互斥的访问同步代码。
2)保证共享变量的修改能够及时可见。
3)有效解决重排序问题。
从语法上讲,Synchronized的应用有三种方式:
1)修饰实例方法,默认使用this作为同步锁。
2)修饰静态方法,默认使用当前方法所在类对象作为同步锁。
3)修饰代码块,锁对象自己选。
Synchronized的同步原理:
Synchronized实现的同步依赖于锁,它可以把任何一个非null对象作为"锁",作用粒度是对象, 可以用来实现临界资源的同步互斥访问,是可重入的。在HotSpot JVM实现中,锁有个专门的名字就是对象监视器(Object Monitor),Synchronized的语义底层就是通过这样的一个monitor的对象来完成同步的。
~~~