1. 谈谈对象的访问定位
对象创建起来之后,就会在虚拟机栈中维护一个本地变量表,用于存储基础类型和基础类型的值,引用类型与引用类型的值。
其中引用类型的值就是堆中对象地址。如何引用堆中地址有两种方式:
- 句柄:在堆中维护一个句柄池,句柄中包含了对象地址,当对象改变的时候,只需改变句柄,不需要改变栈中本地变量表的引用
- 直接指针:对象的地址直接存储在栈中,这样做的好处就是访问速度变快(Hotspot采用该方式)
2. JVM将内存主要划分为哪五部分
方法区、虚拟机栈、本地方法栈、堆、程序计数器。
3. String的intern()函数作用
这个要分版本来回答:
- 如果是JDK6,如果字符串产量池先前已经创建该对象,则返回引用;否则将其添加到字符串常量池并返回引用。
- 如果是JDK6+,若字符串常量池有则返回引用,如果池中没有堆中有,则将堆中的引用添加到池中(注意是引用),然后返回引用;若池中也没有,则在池中创建并返回引用。
4. 本地方法栈和虚拟机栈区别
本地方法栈与虚拟机栈所发挥的作用很相似,他们的区别在于虚拟机栈为执行Java代码方法服务,而本地方法栈是为Native方法服务。
5. 分配堆内存指令
-Xms -Xmx
前者是堆的初始值,后者是堆能达到的最大值。
6. 程序计数器作用
记录当前线程锁执行的字节码的行号。
- 程序计数器是一块较小的内存空间。
- 处于线程独占区。
- 执行java方法时,它记录正在执行的虚拟机字节码指令地址。执行native方法,它的值为undefined
- 该区域是唯一一个没有规定任何OutOfMemoryError的区域
7. 如何将字符串反转?
- 通过 charAt(int index)返回char值进行字符串拼接
- 调用StringBuffer中的reverse方法
8. Collection 和 Collections 有什么区别?
-
Collection 是一个集合接口。它提供了对集合对象进行基本操作的通用接口方法。Collection接口在Java 类库中有很多具体的实现。Collection接口的意义是为各种具体的集合提供了最大化的统一操作方式。
-
Collections 是一个包装类。它包含有各种有关集合操作的静态多态方法。此类不能实例化,就像一个工具类,服务于Java的Collection框架。
9. 在 Queue 中 poll()和 remove()有什么区别?
- queue的增加元素方法add和offer的区别在于,add方法在队列满的情况下将选择抛异常的方法来表示队列已经满了,而offer方法通过返回false表示队列已经满了;在有限队列的情况,使用offer方法优于add方法;
- remove方法和poll方法都是删除队列的头元素,remove方法在队列为空的情况下将抛异常,而poll方法将返回null;
- element和peek方法都是返回队列的头元素,但是不删除头元素,区别在与element方法在队列为空的情况下,将抛异常,而peek方法将返回null.
10. 什么是迭代器
Iterator接口提供了很多对集合元素进行迭代的方法。每一个集合类都包括了可以返回迭代器实例的迭代方法。迭代器可以在迭代过程中删除底层集合的元素,但是不可以直接调用集合的remove(Object obj)删除,可以通过迭代器的remove()方法删除
11. 迭代器的优点
如果用的是for循环,就用集合自带的remove(),而这样就改变了集合的Size()循环的时候会出错。但如果把集合放入迭代器,既iterator迭代可以遍历并选择集合中的每个对象而不改变集合的结构,而把集合放入迭代器,用迭代器的remove()就不会出现问题
12. Java集合类中的Iterator和ListIterator的区别
对List来说,你也可以通过listIterator()取得其迭代器,两种迭代器在有些时候是不能通用的,Iterator和ListIterator主要区别在以下方面:
-
iterator()方法在set和list接口中都有定义,但是ListIterator()仅存在于list接口中(或实现类中);
-
ListIterator有add()方法,可以向List中添加对象,而Iterator不能
-
ListIterator和Iterator都有hasNext()和next()方法,可以实现顺序向后遍历,但是ListIterator有hasPrevious()和previous()方法,可以实现逆向(顺序向前)遍历。Iterator就不可以。
-
ListIterator可以定位当前的索引位置,nextIndex()和previousIndex()可以实现。Iterator没有此功能。
-
都可实现删除对象,但是ListIterator可以实现对象的修改,set()方法可以实现。Iierator仅能遍历,不能修改。
13. 怎么确保一个集合不能被修改?
- Java中提供final关键字,对基本类型进行修饰,当第一次初始化后,该变量就不可被修改
Collections
工具类中的UnmodifiableList
(不可修改的List、Map、Set等)
14. 并行和并发区别
并发的关键是你有处理多个任务的能力,不一定要同时。
15. 说一下你对Daemon线程(守护线程)的理解?它有什么意义?一般应用于什么样的场景?
所谓守护线程是指在程序运行的时候在后台提供一种通用服务的线程,比如垃圾回收线程就是一个很称职的守护者,并且这种线程并不属于程序中不可或缺的部分。因 此,当所有的非守护线程结束时,程序也就终止了,同时会杀死进程中的所有守护线程。反过来说,只要任何非守护线程还在运行,程序就不会终止。
守护线程和用户线程的没啥本质的区别:唯一的不同之处就在于虚拟机的离开:如果用户线程已经全部退出运行了,只剩下守护线程存在了,虚拟机也就退出了。 因为没有了被守护者,守护线程也就没有工作可做了,也就没有继续运行程序的必要了。
16. sleep() 和 wait() 有什么区别?
-
对于sleep()方法,我们首先要知道该方法是属于Thread类中的。而wait()方法,则是属于Object类中的。sleep()方法导致了程序暂停执行指定的时间,让出cpu该其他线程,但是他的监控状态依然保持者,当指定的时间到了又会自动恢复运行状态。在调用sleep()方法的过程中,线程不会释放对象锁。
-
而当调用wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象锁定池准备获取对象锁进入运行状态。
17. notify 和 notifyAll 区别
notify 仅仅通知一个线程,并且我们不知道哪个线程会收到通知,然而 notifyAll 会通知所有等待中的线程。换言之,如果只有一个线程在等待一个信号灯,notify和notifyAll都会通知到这个线程。但如果多个线程在等待这个信号灯,那么notify只会通知到其中一个,而其它线程并不会收到任何通知,而notifyAll会唤醒所有等待中的线程。
18. 线程中start()和run()的区别
-
每个线程都有要执行的任务。线程的任务处理逻辑可以在Tread类的run实例方法中直接实现或通过该方法进行调用,因此run()相当于线程的任务处理逻辑的入口方法,它由Java虚拟机在运行相应线程时直接调用,而不是由应用代码进行调用。
-
而start()的作用是启动相应的线程。启动一个线程实际是请求Java虚拟机运行相应的线程,而这个线程何时能够运行是由线程调度器决定的。start()调用结束并不表示相应线程已经开始运行,这个线程可能稍后运行,也可能永远也不会运行。
19. 线程池的五种状态
线程池的5种状态:Running、ShutDown、Stop、Tidying、Terminated。
20. 线程池中 submit()和 execute()方法有什么区别?
-
execute(Runnable x) 没有返回值。可以执行任务,但无法判断任务是否成功完成。——实现Runnable接口
-
submit(Runnable x) 返回一个future。可以用这个future来判断任务是否成功完成。——实现Callable接口