Java常考面试题
1、什么是JAVA虚拟机?为什么JAVA是与平台无关的语言
java虚拟机是一个可以执行java字节码的虚拟机进程。java源文件被编译成能被java虚拟机执行的字节码文件。
java被设计成可以在任何平台运行,不需要为每个平台单独重写或者重新编译。java虚拟机让这个变为可能,因为它知道底层硬件平台的指令长度和其他特性。
2、JDK和JRE的区别
JRE:java运行时环境,包括java虚拟机、java核心类库和支持文件
JDK:完整的java软件开发包,包含了jre,编译器和其他的工具,可以让开发者开发、编译、执行java应用程序
3、static关键字是什么意思?java是否可以覆盖(override)一个private或者static方法?
static表明成员变量或者成员方法可以在没有所属类的实例变量的情况下访问;
static方法不能被覆盖,因为方法覆盖是基于运行时动态绑定的,static方法是编译时静态绑定的。static方法跟任何实例都不相关,概念上也不适用。
private方法也不可以被覆盖。private修饰的方法和变量只能在当前类中使用。如果是其他类继承当前类是访问不到private方法的,自然也就不能覆盖。
4、是否能在static环境中访问非static变量?
不能。非static变量必须通过实例来访问。如果尝试不用实例访问非static变量,编译器会报错,因为这些变量还没有被创建;
static变量在java中是属于类的,它在所有实例中值都一样。
5、java支持的数据类型?自动拆装箱
8种数据类型:byte short int long float double boolean char
自动装箱:基本数据类型转化为对应的对象包装类型;反之就是拆箱
6、覆盖和重载的意思
覆盖 overriding: 子类重新定义父类的方法,覆盖必须要有相同的方法名,参数列表和返回类型
重载 overload: 同一个类中有两个或多个方法的方法名相同,但是参数不同
7、什么是构造方法?什么是构造方法重载?
新对象被创建时,构造方法会被调用。每一个类都有构造方法。程序员没有给类提供构造方法时,java编译器会为类创造默认的构造方法。
构造方法重载类似于方法重载,可以为一个类创造多个构造方法。每一个构造方法必须要有它自己唯一的参数列表。
8、Java支持多继承吗?
不支持,只支持单继承。但是接口支持多继承,即一个子接口可以有多个父接口
9、接口和抽象类的区别
- 接口中所有方法都是抽象的,抽象类可以同时包含抽象和非抽象方法
- 类可以实现多个接口,但只能继承一个抽象类
- 接口中所有变量默认final,抽象类可以包含非final方法
- 接口的成员函数是public的,抽象类成员函数可以是private,protected或者public
10、值传递和引用传递
值传递:对基本型变量而言,传递的是变量的一个副本,改变副本不影响原变量
引用传递:对于对象型变量而言,传递的是对象地址的一个副本,而非原对象本身
11、进程和线程的区别
进程和线程的区别:
- 地址空间和其他资源:进程间相互独立,同一进程的各线程间相互独立。某进程内的线程在其他进程不可见
- 通信:进程间通信IPC,线程间可以直接读写进程数据段(如全局变量)来进行通信——需要进程同步和互斥手段的辅助,以保证数据的一致性
- 调度和切换:线程上下文切换比进程上下文切换快得多
- 在多线程OS中,进程不是一个可执行的实体
12、创建线程有几种不同方式?你喜欢哪一种?为什么?
有4种方式创建线程:
- 继承Thread类
- 实现Runnable接口
- 应用程序可以使用Executor框架来创建线程池
- 实现Callable接口
13、概括线程的几种可用状态
14、同步方法和同步代码块的区别
- 同步方法默认用this或者当前类class对象作为锁
- 同步代码块可以选择以什么来加锁,比同步方法更细颗粒度,我们可以只同步会发生同步问题的部分代码而不是整个方法
- 同步方法使用关键字synchronized修饰方法,同步代码块主要修饰需要进行同步的代码,用synchronized(object){代码内容}进行修饰
15、监视器内部如何做到线程同步的?程序应该做到那种级别的同步?
监视器和锁在java虚拟机中是一块使用的。监视器监视一块同步代码块,确保一次只有一个线程执行同步代码块。每一个监视器都和一个对象引用相关联。线程在获取锁之前不允许同步执行代码。
16、什么是死锁
死锁是多个进程因竞争资源造成的一种僵局(互相等待),若无外力作用,这些进程都将无法向前推进。死锁产生的4个必要条件:
- 互斥条件:进程要求对所分配的进行排他性控制,即一段时间内某个资源仅为一个进程所占有。此时若有其他进程请求该资源,则请求进程只能等待
- 不剥夺条件:进程所获得的资源在未使用完毕之前,不能被其他进程强行夺走,即只能由获得该资源的进程自己来释放
- 请求和保持条件:进程已经保持了至少一个资源,但又提出了新的资源请求,而该资源已被其他进程占有,此时进程被阻赛,但对自己已经获得的资源保持不放
- 循环等待条件:存在一种进程资源的循环等待链,链中每一个进程已获得的资源同时被链中下一个进程所请求
17.如何确保N个线程可以访问N个资源同时又不导致死锁
制定获取锁的顺序,并强制线程按照制定的顺序获取锁。因此,如果所有的线程都是以同样的顺序加锁和释放锁,就不会出现死锁了。
18、java集合类的接口有哪些?
集合类接口制定了一组叫做元素的对象。集合类接口的每一种具体的实现类都可以选择它自己的方式对元素进行保存和排序。
Java集合类里面最基本的接口有:
- Collection:代表一组对象,每一个对象都是它的子元素
- Set: 不包含重复元素的Collection
- List: 有顺序的Collection,并且可以包含重复元素
- Map:可以把键映射到值得对象,键不能重复
19、为什么集合类没有实现Cloneable和Serializable接口
克隆和序列化的语义和含义是跟具体的实现相关的。因此,应该由集合类的具体实现来决定如何被克隆或者是序列化
20、什么是迭代器(Iterator)?
Iterator接口提供了很多对集合元素进行迭代的方法。每一个集合类都包含了可以返回迭代器实例的迭代方法。迭代器可以在迭代的过程中删除底层集合的元素,但是不可以直接调用集合的remove删除,可以通过迭代器的remove()方法删除。
21.Iterator和ListIterator有什么区别
iterator可用来遍历set和list集合,listIterator只能用来遍历list;
iterator只能前向遍历,ListIterator既可以前向也可以后向;
ListIterator实现了Iterator的接口,并包含其他的功能,比如:增加替换元素,获取前一个和后一个的索引。
22.快速失败和安全失败的区别
java.util包下的集合类都是快速失败的,不能在多线程下发生并发修改;
java.utpil.concurrent包下的容器都是安全失败的,可以在多线程下并发使用,并发修改。
23.HashMap的工作原理
HashMap以键值对的形式存储;HashMap需要一个hash函数,它使用hashcode()和equals()方法从集合中添加和检索元素。当调用put()方法时,HashMap会计算key的hash值,然后把键值对存储在集合中合适的索引上。如果key已经存在,value值会被更新成新值。
24.hashCode()和equals()方法的重要性体现在什么地方?
java的HashMap使用hashCode()和equals()方法来确定键值对的索引,根据键找值的时候也会用到这个方法。如果没有这两个方法,两个不同的键可能会有相同的hash值。因此,可能会被集合认为是相等的。这两个方法也可以用来发现重复元素。
25.HashMap和HashTable的区别
都实现了Map接口;
不同点:
- HashMap允许键和值是null,HashTable不允许null值
- HashTable是同步的,HashMap不同步;HashMap更适合于单线程环境,HashTable适合于多线程环境
- HashMap提供了可供应用迭代的键的合集,因此,HashMap是快速失败的。另一方面,HashTable提供了对键的列举。
26.数组 Array和列表ArrayList有什么区别?
- Array可以包含基本类型和对象类型,ArrayList只能包含对象类型
- ArrayList大小固定,ArrayList的大小是动态变化的
- ArrayList提供了更多的方法和特性,如addAll,removeAll,iterator
27.ArrayList和LinkedList有什么区别?
都实现了list借口,不同点:
- ArrayList是基于索引的数据接口,底层是数组。LinkedList是以元素列表的形式存储数据的;每一个元素和前后的元素都连在一起。
- LinkedList插入添加删除更快,因为它不要重新计算大小或者是更新索引
- LinkedList比ArrayList更占内存,因为LinkedList为每一个节点存储了两个引用,一个指向前一个元素,一个指向下一个元素
28.Comparable和Comparator接口是干什么的?列出区别
- Comparable接口只包含一个compareTo()方法。具体地说,它返回负数,0,正数来表明已经存在的对象小于、等于、大于输入对象
- Comparator 包含compare()和equals()两个方法。compare()方法用来给两个输入参数排序;equals()用来比较输入参数和comparator是否相等
29. 什么是Java优先级队列?
priority queue是一个基于队列优先级的*队列。他的元素按照自然顺序排序。创建时,我们可以给它提供一个负责排序的比较器。priority queue不是线程安全的,入队和出队的时间复杂度都是O(log(n))
30. 过
31.如何权衡有序和无序数组
有序数组查找的时间复杂度是O(logn),无序数组是O(n).
有序数组的缺点是插入的时间复杂度是O(n), 值大的元素需要往后移动来给新元素腾位置。相反,无序数组的插入时间复杂度是O(1)
32.过
33.Enumeration接口和Iterator接口的区别?
Enumeration速度是Iterator的2倍,同时占用更少的内存。
Iterator比Enumeration安全,因为其他线程不能修改正在被Iterator遍历的集合里面的对象。
Iterator允许调用者删除底层集合里面的元素,这对Enumeration来说是不可能的
34.HashSet和TreeSet的区别
HashSet是由一个hash表实现的,因此,它的元素是无序的。add(),remove(),contains()方法的时间复杂度是O(1)
TreeSet是由一个树形的结构来实现的,它里面的元素是有序的。add(),remove(),contains()方法的时间复杂度是O(logn)
35.Java中垃圾回收有什么目的?什么时候进行垃圾回收?
垃圾回收是在内存中存在没有引用的对象或超过作用域的对象时进行的;
垃圾回收的目的是识别并且丢弃应用不再使用的对象来释放和重用资源;
36.System.gc()和Runtime.gc()会做什么事情?
两个方法都用来提示JVM要进行垃圾回收,但是,立即开始还是延迟进行垃圾回收取决于JVM
37.finalize()方法什么时候被调用?析构函数的目的是什么?
垃圾回收器(garbage collector)决定回收某对象时,就会执行对象的finalize()方法。
finalize()主要是用来回收特殊渠道申请的内存。Java程序有垃圾回收器,一般情况下不用程序员操心内存问题。
但有一种JN(Java Native Interface) 调用 non-Java程序(C或者C++),finalize()的工作就是回收这部分的内存。
38. 如果对象的引用被置为null,垃圾收集器是否会立即释放对象占用的内存?
不会,在下一个垃圾回收周期中,这个对象将是可被回收的。
39. Java堆的结构是什么样子的?什么是堆中的永久代(Perm Gen space)?
JVM的堆是运行时数据区,所有类的实例和数组都是在堆上分配内存。它在JVM启动时被创建。对象所占用的堆内存是由垃圾回收器回收的。
堆内存是由内存和死亡的对象组成的。存活的对象是应用可以访问的,不会被垃圾回收。死亡的对象是应用不可访问尚且还没有被垃圾收集器回收掉的对象。一直到垃圾收集器把这些对象回收掉之前,他们会一直占据堆内存空间。
永久代用于存放静态文件,如java类,方法等。
40.串行收集器和吞吐量收集器的区别是什么?
吞吐量收集量使用并行版本的新生代垃圾收集器,它用于中等规模和大数据规模的应用程序。串行收集器多用于小应用。
41.Java中,对象什么时候可以被垃圾回收?
当对象对当前使用这个对象的应用程序变得不可触及的时候,这个对象就可以被回收。
42.JVM的永生代中会发生垃圾回收吗?
垃圾回收不会发生在永生代,如果永生代满了或者超过了临界值,会触发完全垃圾回收。
43.Java两种异常类型?他们的区别是什么?
受检查的异常和不受检查的异常
不受检查的异常不需要再方法或者构造函数上声明,不受检查的异常可以传播到方法或者构造函数的外面。
受检查的异常必须要用throw语句在方法或者是构造函数上声明。
44. Exception和Error有什么区别?
都是Throwable的子类。Exception用于用户程序可以捕获的异常情况,Error定义了不期望被用户程序捕获的异常。
45.throw和throws有什么区别
- throw用于方法内部,throws用于方法声明上
- throw后跟异常对象,throws后跟异常类型
- throw后面只能跟一个异常对象,throws后面一次声明多种异常类型
46.异常处理完成后,exception对象会发生什么变化?
exception对象在下一个垃圾回收过程中被回收掉
47.finally和finalize()方法有什么区别?
无论是否抛出异常,finally都会被执行,它主要用来释放应用程序占用的资源。finalize()方法是object类的一个protected方法,他是在对象被垃圾回收之前由java虚拟机来调用。
48.什么是Applet?
java applet是能够被包含在html页面并且能被启用了java的客户端浏览器执行的程序。applet只要用来创建动态交互的web应用程序。
49.Applet的生命周期
init:每次被载入的时候都会被初始化
start:开始执行applet
stop:结束执行applet
destory:卸载applet之前,做最后的清理工作
50.applet被载入时会发生什么?
首先创建applet控制类的实例,然后初始化applet,最后开始执行。
51.Applet和普通的Java程序有什么区别?
applet运行在启用了java的浏览器中,java应用程序是可以在浏览器之外运行的独立的java程序。但是,他们都需要有java虚拟机。
java应用程序需要一个有特定方法签名的main函数来开始执行。Java applet不需要这样的函数来执行。
Java applet一般会使用很严格的安全策略,java应用一般用比较宽松的安全策略。