快问快答 JAVA 面试36问!我们从面试来反推Java学习。
今天我们来看Java面试题,从大厂梦反推基础学习。
面试题:
- JDK 和 JRE 有什么区别?
- final 在 java 中有什么作用?
- java 中的 Math.round(-1.5) 等于多少?
- String 属于基础的数据类型吗?
- java 中操作 字符串 都有哪些类?它们之间有什么区别?
- String str=”i”与 String str=new String(“i”)一样吗?
- String 类 的常用方法都有那些?
- 普通类和抽象类有哪些区别?
- 接口和抽象类有什么区别?
- java 中 IO 流分为几种?
- BIO、NIO、AIO 有什么区别?
- Files的常用方法都有哪些?
- collection 和 Collections 有什么区别?
- HashMap 和 HashTable 有什么区别?
- 如何决定使用 HashMap 还是 TreeMap?
- 说一下 HashMap 的实现原理?
- 说一下 HashSet 的实现原理?
- ArrayList 和 LinkedList 的区别是什么?
- 如何实现数组和 List 之间的转换?
- ArrayList 和 vector 的区别是什么?
- Array 和 ArrayList 有何区别?
- 在 Queue 中 poll()和 remove()有什么区别?
- 哪些集合类是 线程 安全的?
- 迭代器 Iterator 是什么?
- Iterator 怎么使用?有什么特点?
- Iterator 和 ListIterator 有什么区别?
- 并行和并发有什么区别?
- 线程和进程的区别?
- 守护线程是什么?
- 创建线程有哪几种方式?
- 说一下 runnable 和 callable 有什么区别?
- 线程有哪些状态?
- sleep() 和 wait() 有什么区别?
- notify()和 notifyAll()有什么区别?
- 线程的 run()和 start()有什么区别?
- 创建 线程池 有哪几种方式?
JAVA视频教程_JAVA300集
1. JDK 和 JRE 有什么区别?
⭐JDK:Java Development Kit 的简称,java 开发工具包,提供了 java 的 开发环境 和运行环境。
⭐JRE:Java Runtime Environment 的简称,java 运行环境,为 java 的运行提供了所需环境。
JDK 包含了 JRE,同时还包含了编译 Java 源码的编译器 Javac 和许多Java 程序调试和分析的工具。
如果需要运行 Java ,只需安装 JRE 即可,如果你需要编写 Java 程序,需要安装 JDK。
2. final 在 Java 中有什么作用?
final 修饰的类叫最终类,该类不能被继承。
final 修饰的方法不能被重写。
final 修饰的变量叫常量,而常量必须初始化,初始化之后值便不能被修改。
3. Java 中的 Math.round(-1.5) 等于多少?
等于 -1,在 数轴 上取值时,中间值(0.5)向右取整;正 0.5 是往上取整,负 0.5 是直接舍弃。
4. String 属于基础的数据类型吗?
String 不属于基础类型.
基础类型有 8 种: byte 、 boolean 、char、 short 、int、 float 、long、double,String 属于对象。
5.Java 中操作字符串都有哪些类?它们之间有什么区别?
操作字符串的类有:String、 StringBuffer 、 StringBuilder 。
String 和 StringBuffer、StringBuilder 的区别在于 String 声明的是不可变的对象,每次操作都会生成新的 String 对象,然后将指针指向新的 String 对象,而 StringBuffer、StringBuilder 可以在原有对象的基础上进行操作,所以在经常改变字符串内容的情况下最好不要使用 String。
StringBuffer 和 StringBuilder 最大的区别在于,StringBuffer 是线程安全的,而 StringBuilder 是非线程安全的,但 StringBuilder 的性能却高于 StringBuffer,所以在单线程环境下推荐使用 StringBuilder,多线程环境下推荐使用 StringBuffer。
6. String str=”i”与 String str=new String(“i”)一样吗?
不一样。
内存的分配方式不一样。String str=”i”的方式,java 虚拟机会将其分配到常量池中;而 String str=new String(“i”) 则会被分到堆内存中。
7. String 类的常用方法都有那些?
indexOf():返回指定字符的索引。
charAt ():返回指定索引处的字符。
replace ():字符串替换。
trim():去除字符串两端空白。
split ():分割字符串,返回一个分割后的字符串数组。
get Bytes ():返回字符串的 byte 类型数组。
length ():返回字符串长度。
toLowerCase():将字符串转成 小写字母 。
toUpperCase ():将字符串转成大写字符。
substring():截取字符串。
equals():字符串比较。
8. 普通类和抽象类有哪些区别?
普通类不能包含抽象方法, 抽象类 可以包含抽象方法。
抽象类不能直接实例化,普通类可以直接实例化。
9. 接口和抽象类有什么区别?
实现:抽象类的子类使用 extends 来继承;接口必须使用 implements 来实现接口。
构造函数 :抽象类可以有构造函数;接口不能有。
main 方法:抽象类可以有 main 方法,并且我们能运行它;接口不能有 main 方法。
实现数量:类可以实现很多个接口;但是只能继承一个抽象类。
访问修饰符:接口中的方法默认使用 public 修饰;抽象类中的方法可以是任意访问修饰符。
10. Java 中 IO 流分为几种?
功能:输入流(input)、输出流(output)。
类型:字节流和字符流。
字节流与字符流的区别:
字节流按 8 位传输以字节为单位输入输出数据,字符流按 16 位传输以字符为单位输入输出数据。
11. BIO、NIO、AIO 有什么区别?
⭐BIO:Block IO 同步阻塞式 IO,就是我们平常使用的传统 IO,它的特点是模式简单使用方便,并发处理能力低。
⭐NIO:New IO 同步非阻塞 IO,是传统 IO 的升级,客户端和服务器端通过 Channel(通道)通讯,实现了 多路复用 。
⭐AIO:Asynchronous IO 是 NIO 的升级,也叫 NIO2,实现了异步非堵塞 IO ,异步 IO 的操作基于事件和回调机制。
12. Files的常用方法都有哪些?
- Files. exists ():检测文件路径是否存在。
- Files.create File ():创建文件。
- Files.createDirectory():创建文件夹。
- Files.delete():删除一个文件或目录。
- Files. copy ():复制文件。
- Files.move():移动文件。
- Files.size():查看文件个数。
- Files.read():读取文件。
- Files.write():写入文件。
13. Collection 和 Collections 有什么区别?
Java.util .Collection 是一个集合接口,集合类的一个顶级接口。它提供了对集合对象进行基本操作的通用接口方法。 Collection接口 在Java 类库中有很多具体的实现。Collection接口的意义是为各种具体的集合提供了最大化的统一操作方式,其直接继承接口有List与Set。
Collections则是集合类的一个工具类/帮助类,其中提供了一系列 静态方法 ,用于对集合中元素进行排序、搜索以及线程安全等各种操作。
14. HashMap 和 Hashtable 有什么区别?
⭐HashMap去掉了HashTable 的contains方法,补充添加了containsValue()和containsKey()方法。
⭐HashTable可以同步,HashMap是非同步。
⭐HashMap允许空键值,而HashTable不允许。
15. 如何决定使用 HashMap 还是 TreeMap?
对于在Map中插入、删除和定位元素这类操作,HashMap是最好的选择。
对一个有序的key集合进行遍历,TreeMap是更好的选择。
基于你的collection的大小,也许向HashMap中添加元素会更快,将map换为TreeMap进行有序key的遍历。
16. 说一下 HashMap 的实现原理?
HashMap概述: HashMap是基于 哈希表 的Map接口的非同步实现。此实现提供所有可选的映射操作,并允许使用null值和null键。此类不保证映射的顺序,特别是它不保证该顺序恒久不变。
HashMap的数据结构: 在Java编程语言中,最基本的结构就是两种,一个是数组,另外一个是模拟指针(引用),所有的数据结构都可以用这两个基本结构来构造的,HashMap也不例外。HashMap实际上是一个“链表散列”的数据结构,即数组和 链表 的结合体。
当我们往Hashmap中put元素时,首先根据key的 hashcode 重新计算hash值,根绝hash值得到这个元素在数组中的位置(下标),如果该数组在该位置上已经存放了其他元素,那么在这个位置上的元素将以链表的形式存放,新加入的放在链头,最先加入的放入链尾.如果数组中该位置没有元素,就直接将该元素放到数组的该位置上。
JDK 1.8中对HashMap的实现做了优化,当链表中的节点数据超过八个之后,该链表会转为 红黑树 来提高查询效率,从原来的O(n)到O(logn)
17. 说一下 HashSet 的实现原理?
- HashSet底层由HashMap实现
- HashSet的值存放于HashMap的key上
- HashMap的value统一为PRESENT
18. ArrayList 和 LinkedList 的区别是什么?
ArrrayList底层的数据结构是数组,支持随机访问; LinkedList 的底层数据结构是双向循环链表,不支持随机访问。
使用下标访问一个元素,ArrayList 的时间复杂度是 O(1),而 LinkedList 是 O(n)。
19. 如何实现数组和 List 之间的转换?
⭐List转换成为数组:调用ArrayList的toArray方法。
⭐数组转换成为List:调用Arrays的asList方法。
20. ArrayList 和 Vector 的区别是什么?
1:Vector是同步的,而ArrayList不是。如果寻求在迭代的时候对列表进行改变,应该使用CopyOnWriteArrayList。
2:ArrayList因为有同步比Vector快,不会过载。
3: ArrayList更加通用,因为我们可以使用Collections工具类轻易地获取同步列表和只读列表。
21. Array 和 ArrayList 有何区别?
1:Array可以容纳基本类型和对象,而ArrayList只能容纳对象。
2: Array是指定大小的,而ArrayList大小是固定的。
3:Array没有提供ArrayList那么多功能,比如addAll、removeAll和iterator等。
22. 在 Queue 中 poll()和 remove()有什么区别?
poll() 和 remove() 都是从队列中取出一个元素, poll() 在获取元素失败的时候会返回空, remove() 失败的时候会抛出异常。
23. 哪些集合类是线程安全的?
⭐vector:就比arraylist多了个同步化机制(线程安全),因为效率较低,现在已经不太建议使用。在web应用中,特别是前台页面,往往效率(页面响应速度)是优先考虑的。
⭐statck:堆栈类,先进后出。
⭐hashtable:就比hashmap多了个线程安全。
⭐enumeration:枚举,相当于 迭代器 。
24. 迭代器 Iterator 是什么?
迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象。迭代器因为创建它的代价小通常被称为“轻量级”对象。
25. Iterator 怎么使用?有什么特点?
Java中的Iterator功能比较简单,并且只能单向移动:
1:使用方法:iterator()要求容器返回一个Iterator。第一次调用Iterator的next()方法时,它返回序列的第一个元素。(iterator()方法是 java.lang .Iterable接口,被Collection继承。)
2: 使用next()获得序列中的下一个元素。
3:使用hasNext()检查序列中是否还有元素。
4:使用remove()将迭代器新返回的元素删除。
5:Iterator是Java迭代器最简单的实现,为List设计的 ListIterator 具有更多的功能,它可以从两个方向遍历List,也可以从List中插入和删除元素。
26. Iterator 和 ListIterator 有什么区别?
⭐Iterator可用来遍历Set和List集合,但是ListIterator只能用来遍历List。
⭐Iterator对集合只能是前向遍历,ListIterator既可以前向也可以后向。
⭐ListIterator实现了Iterator接口,并包含其他的功能,如:增加元素获取前一个和后一个元素的索引等。
27. 并行和并发有什么区别?
⭐并行是指两个或者多个事件在同一时刻发生;而并发是指两个或多个事件在同一时间间隔发生。
⭐并行是在不同实体上的多个事件,并发是在同一实体上的多个事件。
⭐在一台处理器上“同时”处理多个任务,在多台处理器上同时处理多个任务。如 hadoop 分布式集群。
并发编程的目标是充分的利用处理器的每一个核,以达到最高的处理性能。
28. 线程和进程的区别?
进程是程序运行和资源分配的基本单位,一个程序至少有一个进程,一个进程至少有一个线程。进程在执行过程中拥有独立的内存单元,而多个线程共享内存资源,减少切换次数,从而效率更高。
线程是进程的一个实体,是 CPU 调度和分派的基本单位,是比程序更小的能独立运行的基本单位。同一进程中的多个线程之间可以并发执行。
29. 守护线程 是什么?
守护线程(即daemon thread),是个服务线程,简单来说也就是服务其他的线程。
30. 创建线程有哪几种方式?
1:继承Thread类创建线程类
定义Thread类的子类,并重写该类的run方法,该run方法的方法体就代表了线程要完成的任务。因此把run()方法称为执行体。
创建 Thread 子类的实例,即创建了线程对象。
调用线程对象的start()方法来启动该线程。
2:通过Runnable接口创建线程类
定义runnable接口的实现类,并重写该接口的run()方法,该run()方法的方法体同样是该线程的线程执行体。
创建 Runnable实现类的实例,并依此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象。
调用线程对象的start()方法来启动该线程。
3:通过Callable和Future创建线程
创建Callable接口的实现类,并实现call()方法,该call()方法将作为线程执行体,并且有返回值。
创建Callable实现类的实例,使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法的返回值。
使用FutureTask对象作为Thread对象的target创建并启动新线程。
调用FutureTask对象的get()方法来获得子线程执行结束后的返回
31. 说一下 Runnable 和 Callable 有什么区别?
⭐Callable接口中的call()方法是有返回值的,是一个 泛型 ,和Future、FutureTask配合可以用来获取异步执行的结果。
32. 线程有哪些状态?
线程通常都有五种状态,创建、就绪、运行、阻塞和死亡。
1:创建状态。在生成线程对象,并没有调用该对象的start方法,这是线程处于创建状态。
2:就绪状态。当调用了线程对象的start方法之后,该线程就进入了就绪状态,但是此时线程调度程序还没有把该线程设置为当前线程,此时处于就绪状态。在线程运行之后,从等待或者睡眠中回来之后,也会处于就绪状态。
3:运行状态。线程调度程序将处于就绪状态的线程设置为当前线程,此时线程就进入了运行状态,开始运行run函数当中的代码。
4:阻塞状态。线程正在运行的时候,被暂停,通常是为了等待某个时间的发生(比如说某项资源就绪)之后再继续运行。sleep,suspend,wait等方法都可以导致线程阻塞。
5:死亡状态。如果一个线程的run方法执行结束或者调用stop方法后,该线程就会死亡。对于已经死亡的线程,无法再使用start方法令其进入就绪
33. sleep() 和 wait() 有什么区别?
sleep():方法是线程类(Thread)的静态方法,让调用线程进入睡眠状态,让出执行机会给其他线程,等到休眠时间结束后,线程进入就绪状态和其他线程一起竞争cpu的执行时间。因为sleep() 是static静态的方法,他不能改变对象的机锁,当一个 synchronized 块中调用了sleep() 方法,线程虽然进入休眠,但是对象的机锁没有被释放,其他线程依然无法访问这个对象。
wait():wait()是Object类的方法,当一个线程执行到wait方法时,它就进入到一个和该对象相关的等待池,同时释放对象的机锁,使得其他线程能够访问,可以通过notify,notifyAll方法来唤醒等待的线程。
34. notify()和 notifyAll()有什么区别?
⭐如果线程调用了对象的 wait()方法,那么线程便会处于该对象的等待池中,等待池中的线程不会去竞争该对象的锁。
⭐当有线程调用了对象的 notifyAll()方法(唤醒所有 wait 线程)或 notify()方法(只随机唤醒一个 wait 线程),被唤醒的的线程便会进入该对象的锁池中,锁池中的线程会去竞争该对象锁。也就是说,调用了notify后只要一个线程会由等待池进入锁池,而notifyAll会将该对象等待池内的所有线程移动到锁池中,等待锁竞争。
⭐优先级高的线程竞争到对象锁的概率大,假若某线程没有竞争到该对象锁,它还会留在锁池中,唯有线程再次调用 wait()方法,它才会重新回到等待池中。而竞争到对象锁的线程则继续往下执行,直到执行完了 synchronized 代码块,它会释放掉该对象锁,这时锁池中的线程会继续竞争该对象锁。
35. 线程的 run()和 start()有什么区别?
每个线程都是通过某个特定Thread对象所对应的方法run()来完成其操作的,方法run()称为线程体。通过调用Thread类的start()方法来启动一个线程。
start()方法来启动一个线程,真正实现了多线程运行。这时无需等待run方法体代码执行完毕,可以直接继续执行下面的代码; 这时此线程是处于就绪状态, 并没有运行。 然后通过此Thread类调用方法run()来完成其运行状态, 这里方法run()称为线程体,它包含了要执行的这个线程的内容, Run方法运行结束, 此线程终止。然后CPU再调度其它线程。
run()方法是在本线程里的,只是线程里的一个函数,而不是多线程的。 如果直接调用run(),其实就相当于是调用了一个普通函数而已,直接待用run()方法必须等待run()方法执行完毕才能执行下面的代码,所以执行路径还是只有一条,根本就没有线程的特征,所以在多线程执行时要使用start()方法而不是run()方法。
36. 创建线程池有哪几种方式?
1: newFixedThreadPool(int nThreads)
创建一个固定长度的线程池,每当提交一个任务就创建一个线程,直到达到线程池的最大数量,这时线程规模将不再变化,当线程发生未预期的错误而结束时,线程池会补充一个新的线程。
2:newCachedThreadPool()
创建一个可缓存的线程池,如果线程池的规模超过了处理需求,将自动回收空闲线程,而当需求增加时,则可以自动添加新线程,线程池的规模不存在任何限制。
3: newSingleThreadExecutor()
这是一个单线程的Executor,它创建单个工作线程来执行任务,如果这个线程异常结束,会创建一个新的来替代它;它的特点是能确保依照任务在队列中的顺序来串行执行。
4:newScheduledThreadPool(int corePoolSize)
创建了一个固定长度的线程池,而且以延迟或定时的方式来执行任务,类似于Timer。
这就是今天的快问快答了,还有什么需求请少侠尽快告诉我,我们一起努力向前!