一、Java 基础
1.JDK 和 JRE 有什么区别?
JDK是java的开发工具包,包含各种类库,并且包含了JRE,javac是在JDK中的;
JREjava程序的运行环境,安装过程中自动添加PATH.
-
== 和 equals 的区别是什么?
一. 对于==,比较的是值是否相等,如果比较的是基本数据类型的变量,则直接比较其存储的值是否相等,
如果比较的是引用数据类型,则比较的是所指向的对象的地址值.
二. equals不能作用于基本数据类型,它比较的是是否是同一个对象
如果没有对equals方法进行重写,则比较的是引用类型的变量所指向的对象的地址值.
如String,Date等类对equals方法进行了重写,比较的则是所指向的对象的内容 -
两个对象的 hashCode()相同,则 equals()也一定为 true,对吗?
首先,两个对象equals相等,hashcode一定相等;但是hashcode相等时,equals不一定相等.
其次,两个不同的对象,因为可能存在哈希碰撞,所以hashcode可能是相等的,但是显然equals不为true.
还有就是,在object类中,euqals方法还是用的==来判断的,==对于对象而言比较的是地址值,所以equals相等
hashcode一定一样,反之就不一定了. -
final 在 java 中有什么作用?
final关键字可作用于类,类属性和方法;
作用于类上时,该类不能被继承
作用于属性时,该属性不能被重新复制
作用于方法时,该方法不能被重写 -
java 中的 Math.round(-1.5) 等于多少?
Math的round方法是四舍五入,如果参数是负数,则往大的数如,Math.round(-1.5)=-1 -
String 属于基础的数据类型吗?
不是,String是一个类,是引用数据类型. -
java 中操作字符串都有哪些类?它们之间有什么区别?
有String,StringBuilder,StringBuffer- String是不可变的,每次对String的操作都会产生一个String对象
- StringBuilder和StringBuffer是可变的,能够被多次修改,并不会产生新的对象.
- StringBuilder是线程不安全的,StringBuffer是线程安全的.
- StringBuilder的处理速度比StringBuffer要快
-
String str="i"与 String str=new String(“i”)一样吗?
他们的值相等,用equals得到true,但是他们是两个对象,如果用==判断返回false.
且str="i"是直接在常量池中引用字符串,而new String(“i”)是在堆中根据i再创建一个对象. -
如何将字符串反转?
- 通过StringBuilder的reverse()方法可以直接反转
StringBuilder sb = new StringBuilder(“abc”);
sb.reverse().toString(); - 通过String的toCharArray方法可以获得字符串每一个字符并且转换为字符数组
然后循环从后往拼接即可 - 递归的方法反转(当只有一个字符时,返回原字符;当有两个以上的字符时,返回结果为第二个字符串开始的子串+第一个字符)
public String reverseString(String str) {
if ((null == str) || str.length()<2) {
return str;
}
return reverseString(str.subString(1)) +str.charAt(0);
}
- 通过StringBuilder的reverse()方法可以直接反转
-
String 类的常用方法都有那些?
charAt(int index)返回指定索引处的字符
length()返回字符串长度
split()根据给定的正则表达式拆分字符串
toString()返回此对象本身 -
抽象类必须要有抽象方法吗?
抽象类可以没有抽象方法,但是如果一个类已经声明为抽象类,那么它也不能再实例化,不能直接构造该类对象. -
普通类和抽象类有哪些区别?
- 抽象类不能被实例化,普通类反之
- 抽象类的访问权限限于public和protected,如果为private的话,就不能被子类继承了.
- 如果一个类继承于抽象类,则它必须实现父类的抽象方法.如果不想实现,那么子类也必须是抽象类.
-
抽象类能使用 final 修饰吗?
不能,final修饰的类是不能被继承的,如果抽象类不能继承,就没有意义了. -
接口和抽象类有什么区别?
- 抽象类可以有构造方法,接口不能有构造方法.
- 抽象类可以包含非抽象方法,接口则不能.
- 抽象类方法访问权限是public、protected,接口中只能是public.
- 只能单继承,但是可以多实现.
-
java 中 IO 流分为几种?
大的方面来说有两种:字节流和字符流
字节流继承于InputStream、OutputStream
字符流继承于Reader、Writer -
BIO、NIO、AIO 有什么区别?
- BIO表示同步阻塞式IO,交互方式是同步、阻塞方式,即客户端有连接请求时服务端就需要启动一个线程进行处理,
如果这个连接不做任何事情会造成不必要的开支. - NIO表示同步非阻塞IO,客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求
时才启动一个线程处理. - AIO表示异步非阻塞IO,客户端的I/O请求都是由操作系统先完成IO操作后再通知服务器应用来启动线程处理.
- BIO表示同步阻塞式IO,交互方式是同步、阻塞方式,即客户端有连接请求时服务端就需要启动一个线程进行处理,
-
Files的常用方法都有哪些?
String getName():返回File对象所表示的文件名或文件路径
String getPath():返回File对象所对应的相对路径
boolean exists():判断File对象的文件或者目录是否存在
boolean isDirectory():判断File对象是否是目录
二、容器
18. java 容器都有哪些?
String,数组以及java.util下面的集合类
List:存放有序,列表存储,元素可重复
ArrayList LinkedList Vector
Set:无序,元素不可重复
HashSet TreeSet
Map:无序,元素可重复
HashMap TreeMap LinkedHashMap HashTable
19. Collection 和 Collections 有什么区别?
Collection是集合类的一个顶级接口,它提供了对集合对象进行基本操作的通用接口方法.
Collections是集合类的一个工具类,它提供了一系列的静态方法,用于对集合中元素进行排序,搜索以及线程同步等操作.
20. List、Set、Map 之间的区别是什么?
List: 可以允许重复的对象;
可以插入多个null元素;
有序,输入顺序就是输出顺序;
Set: 不允许重复对象;
无序,且只允许一个null对象;
Map: 存储键值对,只能有唯一的key,value可以重复
只能有一个null键
21. HashMap 和 Hashtable 有什么区别?
一. HashMap可以接受null键和值,HashTable不行
二. HashTable是线程安全的,通过synchronized来保证,而HashMap线程不安全
三. HashMap的迭代器是fail-fast迭代器,而HashTable的enumerator迭代器不是fail-fast.
22. 如何决定使用 HashMap 还是 TreeMap?
HashMap基于散列表实现,适用于查询频繁的情况
TreeMap基于红黑树实现,适用于创建比较多的情况.且TreeMap存储数据是按照字母表的顺序存储的,
如果对顺序有要求也可以选用TreeMap.
23. 说一下 HashMap 的实现原理?
数组+链表,初始16,75扩容,数据存在内部类Map.Entry中,其中包含key value hashcode和next.
24. 说一下 HashSet 的实现原理?
HashSet基于HashMap实现,默认构造函数是构造一个初始容量为16的HashMap,所有放入HashSet
集合的元素实际上由HashMap的key来保存,而value则保存了一个PRESENT的静态Object对象,因为元素都保存在key
中,所以才能不重复.
25. ArrayList 和 LinkedList 的区别是什么?
1. ArrayList底层基于动态数组,LinkedList基于链表实现,底层是循环双向链表
2. 对于随机访问get和set,ArrayList优于LinkedList.
3. 对于新增add和删除remove,LinkedList比较快
26. 如何实现数组和 List 之间的转换?
List转数组:toArray()方法.在方法参数中指定原集合的长度的数组即可.
数组转List:Arrays的asList()方法.
27. ArrayList 和 Vector 的区别是什么?
1. Vector的方法都是同步的,是线程安全的,ArrayList则不是.
2. 在进行扩容的时候,Vector扩容至原来的一倍,ArrayList增加至原来的0.5倍.
28. Array 和 ArrayList 有何区别?
1. Array(数组)可以包含基本数据类型和对象类型,ArrayList只能包含对象类型.
2. ArrayList可以自动扩容,Array则不行.
29. 在 Queue 中 poll()和 remove()有什么区别?
Queue中,add方法和offer方法都可以添加元素,而remove和poll都是删除队列的头元素,区别在于:
add方法在队列满的情况下抛异常,而offer方法则返回false.
remove方法在队列为空时抛异常,poll方法将返回null.
30. 哪些集合类是线程安全的?
Vector HashTable ConcurrentHashMap
Stack
31. 迭代器 Iterator 是什么?
Iterator是个接口,它提供了很多对元素进行迭代的方法.迭代器可以在迭代过程中删除
底层集合的元素,可以直接调用Iterator的remove()方法来删除.
因为在Conllection接口中定义了获取集合迭代器的方法,所以每一个集合都包括了可以返回迭代器实例的方法.
32. Iterator 怎么使用?有什么特点?
每个集合都可以用iterator()方法一个Iterator实例.
使用next()方法获取序列中的下一个元素,使用hasNext()方法检查序列中是否有元素
使用remove()方法将迭代器新返回的方法删除.
特点:Iterator将集合的遍历和其底层的结构分离.
33. Iterator 和 ListIterator 有什么区别?
ListIterator是Iterator的子接口,用于扩展Iterator.
在Iterator中,我们只能向前移动,无法操纵或者修改集合中的元素.ListIterator弥补了这种缺点
区别: 1.范围不同,Iterator适用于所有集合,而ListIterator只适用于List及其子类
2.ListIterator有add方法可以添加元素,Iterator则不行.
3.ListIterator可以实现双向遍历,Iterator则不行.
4.ListIterator可以实现对象的修改,Iterator不行
5.ListIterator可以获取集合中的所有,Iterator不行.
34. 怎么确保一个集合不能被修改?
可以使用Collections或者Guava来快速实现.如Collections.unmodifiableMap(xxxMap);
三、多线程
35. 并行和并发有什么区别?
并行是多个事件同时进行,并发是多个事件在某一时间段内间隔发生.
你吃饭吃到一半,电话来了,你停了下来接了电话,接完后继续吃饭,这说明你支持并发。
你吃饭吃到一半,电话来了,你一边打电话一边吃饭,这说明你支持并行。
36. 线程和进程的区别?
进程是操作系统资源分配的基本单位,线程是任务调度和执行的基本单位.
进程有独立的地址空间,一个进程崩溃后在保护模式下不会对其他进程产生影响,而线程只是一个进程中的
不同执行路径,线程有自己的堆栈和局部变量.在操作系统中能同时运行多个进程,而在同一个进程内有多个
线程同时执行.
37. 守护线程是什么?
守护线程是服务其他线程的,在java中,线程有两种:守护线程和用户线程.
java中的jvm垃圾回收线程就是一个典型的守护线程.当用户线程全部执行完,包括main线程也执行完毕,那么
jvm会自动退出,此时守护线程也就停止了.
38. 创建线程有哪几种方式?
三种: 1. 继承Thread类,重写run方法,用子类实例调用start()方法;
2. 实现Runnable接口并重写run方法,创建Thread实例并传入Runnable实例,代用Thread的start()方法
3. 创建Callable接口的实现类,重写call方法;
构造此实现类的实例,将其作为参数构造一个FutureTask类的实例;
以FutureTask的实例为参数构造一个Thread对象执行start()方法.
第三种方式可以允许有返回值,也可以声明抛出异常类.
39. 说一下 runnable 和 callable 有什么区别?
runnable方式时,多个线程间可以共享实例变量,callable方式则不行
runnable方式没有返回值,callable有返回值
runnable方式run方法的异常只能在内部消化,callable的call()方法允许抛出异常
40. 线程有哪些状态?
1. NEW 新建状态,此时线程还没有运行线程中的代码
2. RUNNABLE 就绪状态;处于就绪状态的线程并不一定立即运行run方法,必须还要和其他线程竞争CPU时间
3. RUNNING 运行状态;线程获得CPU时间后才进入运行状态,开始执行run方法
4. BLOCKED 阻塞状态;线程运行过程中会有各种原因来进入阻塞状态,如:调用sleep方法进入休眠;
在IO操作中被阻塞;试图得到一个锁,该锁正被其他线程持有;等待某个触发条件.
阻塞状态的线程此时没有结束,暂时让出CPU时间给其他线程.
5. DEAD 死亡状态;有两个原因导致线程死亡:第一是run方法正常退出自然死亡;第二是一个未捕获的
异常终止了run方法使线程死亡.
为了确定线程在当前是否存活着(就是要么是可运行的,要么是被阻塞了),需要使用isAlive方法,如果是可运行或被阻塞,这个方法返回true;如果线程仍旧是new状态且不是可运行的,或者线程死亡了,则返回false。
41. sleep() 和 wait() 有什么区别?
1. sleep方法使Thread类的,而wait方法使Object类中的
2. sleep方法使线程暂停指定的时间,让出CPU给其他线程,但是他的监控状态依然保持着,时间到了以后会自动恢复运行状态
在这个过程中,线程不会释放同步对象锁.
而调用wait方法,线程会放弃对象锁,进入等待队列,待调用notify/notifyAll方法后才会进入锁池,获取对象锁后才进入运行状态.
42. notify()和 notifyAll()有什么区别?
notify()方法随机唤醒一个wait线程到锁池中去竞争锁,而notifyAll方法唤醒所有wait线程到锁池.
no