Java面试题大全带答案

14. 接口和抽象类有什么区别?

  • 抽象类的子类要用 extends 来继承;而实现接口要用 implements 。

  • 抽象类可以定义构造函数,而接口不能。

  • 抽象类里可以定义 main 方法,但接口不能有 main 方法。

  • 实现数量:类可以实现很多个接口;但是只能继承一个抽象类。

  • 访问修饰符:接口中的方法默认使用 public 修饰;抽象类中的方法可以是任意访问修饰符。

上述是从语法上来归纳,然后建议大家再从面向对象思想的角度来说明

  • 抽象类是对逻辑的归纳,比如动物类可以是抽象类,人类可以extends动物这个抽象类。

  • 而接口是对功能的归纳,比如可以定义一个“提供数据库访问功能”的 接口,在其中封装若干操作数据库的方法。

15. java 中 IO 流分为几种?

按功能来分可以分输入流(input)和输出流(output)。从类型来分可以是字节流和字符流。

16. BIO、NIO、AIO 有什么区别?

  • BIO的英语全称是Block IO, 同步阻塞式 IO,就是平常经常使用的传统 IO,特点是简单方便,但并发处理能力低。

  • NIO,叫New IO, 同步非阻塞 IO,客户端和服务器端通过 Channel(通道)通讯,实现了多路复用。

  • AIO,Asynchronous IO, 是 NIO 的升级,实现了异步非堵塞 IO ,它是基于事件和回调机制。

17. Files的常用方法都有哪些?

  • Files.exists():检测路径是否存在。

  • Files.createFile():创建文件。

  • Files.createDirectory():创建文件夹。

  • Files.delete():删除文件或文件夹。

  • Files.copy():复制文件。

  • Files.move():移动文件,即复制后删除。

  • Files.size():查看文件的个数。

  • Files.read():读取文件。

  • Files.write():写入文件。


第二部分,Java的集合,也叫容器

==================================================================================

18. java 的集合容器都有哪些?

如下给出了大致的结构

  • 所有线性表对象的父类是Collection

  • 有线性表类,比如ArrayList和Set等。

  • 有键值对类,比如HashMap。

19. Collection 和 Collections 有什么区别?

  • Collection 是一个集合接口,是所有线性表对象的父类。

  • Collections是集合类的一个工具类,包含了对集合元素进行排序和线程安全等各种操作方法。

20. List、Set、Map 之间的区别是什么?

21. HashMap 和 Hashtable 有什么区别?

首先说,两者都是键值类的对象

  • HashTable线程安全的,而HashMap线程不安全的,大多数的场景是单线程环境,在单线程环境下,HashMap效率上比hashTable要高。

  • HashMap允许空键值,而hashTable不允许。

22. 如何决定使用 HashMap 还是 TreeMap?

对于在Map中进行插入、删除和定位元素这类操作,可以选HashMap。但如果你要对一个有序的key集合进行遍历,需要选TreeMap。

23. 说一下 HashMap 的实现原理?

HashMap是基于数据结构里的散列表,在大数据情况下,能保证get的高效性。

HashMap不保证映射的顺序,特别是它不保证该顺序恒久不变。

HashMap实际上是一个“链表散列”的数据结构,即数组和链表的结合体。

当向Hashmap对象里put元素时,会根据key的hashcode计算hash值,根据hash值得到这个元素在数组中的位置,如果该数组在该位置上已经存放了其他元素,那么在这个位置上的元素将以链表的形式存放,新加入的放在链头,最先加入的放入链尾.如果数组中该位置没有元素,就直接将该元素放到数组的该位置上。

注意Jdk 1.8中对HashMap的实现做了优化,当链表中的节点数据超过八个之后,该链表会转为红黑树来提高查询效率,从原来的O(n)到O(logn)

24. 说一下 HashSet 的实现原理?

  • HashSet在底层上,是由HashMap实现的

  • HashSet的值放在HashMap的key上

  • HashMap的value统一为PRESENT

25. ArrayList 和 LinkedList 的区别是什么?

ArrrayList底层实现的数据结构是数组,支持随机访问,而 LinkedList 的底层数据结构是双向循环链表,不支持随机访问。

使用下标访问一个元素,ArrayList 的时间复杂度是 O(1),而 LinkedList 是 O(n)。

26. 如何做到数组和 List之间的转换?

  • List对象转换成为数组:可以调用ArrayList(或其它List)的toArray方法。

  • 数组转换成为List:调用Arrays的asList方法。

27. ArrayList 和 Vector 的区别是什么?(面试大概率会问)

  • Vector是线程安全的,而ArrayList不是。所以在单线程情况下,建议使用ArrayList

  • 在扩容时,Vector是扩容100%,但ArrayList是50%,后者更节省内存

结论:大多数开发场景是单线程环境,所以建议使用ArrayList

28. Array 和 ArrayList 有何区别?

  • Array能容纳基本数据类型和自定义对象,而ArrayList只能容纳自定义的对象,对于基本数据类型,需要转换成封装类才能存储。

  • Array是指定大小的,要手动扩容,而ArrayList大小虽然可以在定义时指定,但遇到容量满时会自动扩容。

  • Array没有提供ArrayList那么多功能,比如addAll、removeAll和iterator等。

所以建议使用ArrayList

29. 在 Queue 中 poll()和 remove()有什么区别?

poll() 和 remove() 都是从队列中取出一个元素,但是 poll() 在获取元素失败的时候会返回空,但是 remove() 失败的时候会抛出异常。

30. 哪些集合类是线程安全的?

  • Vector:就比arraylist多了个同步化机制(线程安全),因为效率较低,现在已经不太建议使用。在web应用中,特别是前台页面,往往效率(页面响应速度)是优先考虑的。

  • Statck:堆栈类,先进后出,项目中用得并不多。

  • Hashtable:就比hashmap多了个线程安全,所以建议使用HashMap。

  • enumeration:枚举,所以现在建议用Iterator来迭代。

结论是,如果在单线程情况下,不建议使用这些线程安全对象。

31. 迭代器 Iterator 是什么?

迭代器是一种设计模式,也是一个对象,可以用来遍历并选择序列(比如ArrayList或HashMap)中的对象,而开发人员不需要了解该序列的底层结构。

迭代器通常被称为“轻量级”对象,因为创建它的代价小。

32. Iterator 怎么用?有什么特点?

Iterator比较好用,而且只能单向移动:

(1) 使用方法iterator()要求容器返回一个Iterator。第一次调用Iterator的next()方法时,它返回序列的第一个元素。比如list.iterator()

(2) 用next()得到序列中的下一个元素。

(3) 使用hasNext()检查是否还有其它元素。

(4) 使用remove()将迭代器新返回的元素删除。但不建议一遍迭代一边删除,有可能引发并发问题。

Iterator是Java迭代器最简单的实现,为List设计的ListIterator具有更多的功能,它可以从两个方向遍历List,也可以从List中插入和删除元素。

33. Iterator 和 ListIterator 有什么区别?

  • Iterator可用来遍历Set和List集合,但是ListIterator只能用来遍历List。

  • Iterator对集合只能是前向遍历,ListIterator既可以前向也可以后向。

  • ListIterator实现了Iterator接口,并包含其他的功能,比如:增加元素,替换元素,获取前一个和后一个元素的索引等等,但在实际用的时候,大多也是只用到迭代的功能。

  • 一般只建议使用Iterator,别区分地对List对象用ListIterator。


第三部分、多线程

==========================================================================

35. 并行和并发有什么区别?

  • 并行是指两个或多个事件在同一时刻发生;而并发是指两个或多个事件在同一时间间隔发生。

  • 并行是在不同实体上的多个事件,并发是在同一实体上的多个事件。

  • 在一台处理器上“同时”处理多个任务,在多台处理器上同时处理多个任务。如hadoop分布式集群。

  • 实际应用场景里,一般是考虑多并发问题,而不是多并行问题。

36. 线程和进程的区别?

进程是程序运行和资源分配的基本单位,一个程序至少有一个进程,一个进程至少有一个线程,但一个进程一般有多个线程。

进程在运行过程中,需要拥有独立的内存单元,否则如果申请不到,就会挂起。而多个线程能共享内存资源,这样就能降低运行的门槛,从而效率更高。

线程是是cpu调度和分派的基本单位,在实际开发过程中,一般是考虑多线程并发。

37. 守护线程是什么?

守护线程(daemon thread),是个服务线程,用来监视和服务其它线程。

38. 创建线程有哪几种方式?

①. 继承Thread类创建线程类

  • 通过extends Thread定义Thread类的子类,并重写该类的run方法。

  • 创建Thread子类的实例,并调用线程对象的start()方法来启动该线程。

②. 通过Runnable接口创建线程类

  • implements Runnable接口的实现类,并重写该接口的run()方法。

  • 创建 Runnable实现类的实例,并依此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象。

  • 调用线程对象的start()方法来启动该线程。

③. 通过Callable和Future创建线程

  • 创建Callable接口的实现类,并实现call()方法,该call()方法将作为线程执行体,并且有返回值。

  • 创建Callable实现类的实例,使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法的返回值。

  • 使用FutureTask对象作为Thread对象的target创建并启动新线程。

  • 调用FutureTask对象的get()方法来获得子线程执行结束后的返回值。

另外,还有通过线程池来创建线程

39. 说一下 runnable 和 callable 有什么区别?

  • Runnable接口中的run()方法的返回值是void,在其中可以定义线程的工作任务,但无法返回值。

  • Callable接口中的call()方法是有返回值的,是一个泛型,一般会和Future、FutureTask配合,能异步地得到线程的执行结果。

40. 线程有哪些状态?

线程通常都有五种状态,创建、就绪、运行、阻塞和死亡。

  • 创建状态。创建好线程对象,并没有调用该对象的start方法,此时线程处于创建状态。

  • 就绪状态。当调用线程对象的start方法之后,该线程就进入了就绪状态,但是此时线程调度程序还没有把该线程设置为当前线程,也就是说还没进入运行状态。或者在线程运行之后,从等待或者睡眠状态中回来之后,也会处于就绪状态,等待被调度进入运行状态。

  • 运行状态。线程调度程序将处于就绪状态的线程设置为当前线程,此时线程就进入了运行状态,开始运行run函数当中的代码。

  • 阻塞状态。线程正在运行的时候,被暂停,通常是为了等待某个实践的发生(比如说某项资源就绪)之后再继续运行。wait方法都可以导致线程阻塞。

  • 死亡状态。如果一个线程的run方法执行结束或者调用stop方法后,该线程就会死亡。对于已经死亡的线程,无法再使用start方法令其进入就绪

41. sleep() 和 wait() 有什么区别?

sleep():这是线程类(Thread)的静态方法,让线程进入睡眠状态,等休眠时间结束后,线程进入就绪状态,和其他线程一起竞争cpu的执行时间。

因为sleep() 是static静态的方法,他不能改变对象的机锁,当一个synchronized块中调用了sleep() 方法,线程虽然进入休眠,但是对象的机锁没有被释放,其他线程依然无法访问这个对象,这时就会引发问题,此类现象请注意。

wait():wait()是Object类的方法,当一个线程执行到wait方法时,它就进入到一个和该对象相关的等待池,同时释放对象的机锁,使得其他线程能够访问,可以通过notify,notifyAll方法来唤醒等待的线程。

42. notify()和 notifyAll()有什么区别?

  • 如果线程调用了对象的 wait()方法,那么线程便会处于该对象的等待池中,等待池中的线程不会去竞争该对象的锁,而且被wait的线程,无法自动再进入到唤醒状态。

  • 当有线程调用了对象的 notifyAll()方法(唤醒所有 wait 线程)或 notify()方法(只随机唤醒一个 wait 线程),被唤醒的的线程便会进入该对象的锁池中,锁池中的线程会去竞争该对象锁。也就是说,调用了notify后只要一个线程会由等待池进入锁池,而notifyAll会将该对象等待池内的所有线程移动到锁池中,等待锁竞争。

  • 优先级高的线程竞争到对象锁的概率大,假若某线程没有竞争到该对象锁,它还会留在锁池中,唯有线程再次调用 wait()方法,它才会重新回到等待池中。而竞争到对象锁的线程则继续往下执行,直到执行完了 synchronized 代码块,它会释放掉该对象锁,这时锁池中的线程会继续竞争该对象锁。

43. 线程的 run()和 start()有什么区别?

每个线程都是通过运行自身run()来完成其操作的。而一般要通过调用Thread类的start()方法(不是run方法)来启动一个线程。

start()方法来启动一个线程,真正实现了多线程运行。这时无需等待run方法体代码执行完毕,可以直接继续执行下面的代码; 这时此线程是处于就绪状态, 并没有运行。

然后通过此Thread类调用方法run()来完成其运行状态, Run方法运行结束后, 此线程终止。然后CPU再调度其它线程。

run()方法是在本线程里的,只是线程里的一个函数,而不是多线程的。 如果直接调用run(),其实就相当于是调用了一个普通函数而已,而不是以多线程的方式来运行。

总之,在多线程执行时要使用start()方法而不是run()方法。

44. 创建线程池有哪几种方式?

①. newFixedThreadPool(int nThreads)

创建一个固定长度的线程池,每当提交一个任务就创建一个线程,直到达到线程池的最大数量,这时线程规模将不再变化,当线程发生未预期的错误而结束时,线程池会补充一个新的线程。

②. newCachedThreadPool()

创建一个可缓存的线程池,如果线程池的规模超过了处理需求,将自动回收空闲线程,而当需求增加时,则可以自动添加新线程,线程池的规模不存在任何限制。

③. newSingleThreadExecutor()

这是一个单线程的Executor,它创建单个工作线程来执行任务,如果这个线程异常结束,会创建一个新的来替代它;它的特点是能确保依照任务在队列中的顺序来串行执行。

④. newScheduledThreadPool(int corePoolSize)

创建了一个固定长度的线程池,而且以延迟或定时的方式来执行任务,类似于Timer。

45. 线程池都有哪些状态?

线程池有5种状态:Running、ShutDown、Stop、Tidying、Terminated。

线程池各个状态切换框架图:

46. 线程池中 submit()和 execute()方法有什么区别?

  • 接收的参数不一样

  • submit有返回值,而execute没有

  • submit方法能进行Exception处理

47. 在 java 程序中怎么保证多线程的运行安全?

线程安全在三个方面体现:

  • 原子性:提供互斥访问,同一时刻只能有一个线程对数据进行操作,(atomic,synchronized);

  • 可见性:一个线程对主内存的修改可以及时地被其他线程看到,(synchronized,volatile);
    先自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《Java开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以扫码领取!

img

最后

权威指南-第一本Docker书

引领完成Docker的安装、部署、管理和扩展,让其经历从测试到生产的整个开发生命周期,深入了解Docker适用于什么场景。并且这本Docker的学习权威指南介绍了其组件的基础知识,然后用Docker构建容器和服务来完成各种任务:利用Docker为新项目建立测试环境,演示如何使用持续集成的工作流集成Docker,如何构建应用程序服务和平台,如何使用Docker的API,如何扩展Docker。

总共包含了:简介、安装Docker、Docker入门、使用Docker镜像和仓库、在测试中使用Docker、使用Docker构建服务、使用Fig编配Docke、使用Docker API、获得帮助和对Docker进行改进等9个章节的知识。

image

image

image

image

关于阿里内部都在强烈推荐使用的“K8S+Docker学习指南”—《深入浅出Kubernetes:理论+实战》、《权威指南-第一本Docker书》,看完之后两个字形容,爱了爱了!
d36.jpg" alt=“img” style=“zoom: 33%;” />

最后

权威指南-第一本Docker书

引领完成Docker的安装、部署、管理和扩展,让其经历从测试到生产的整个开发生命周期,深入了解Docker适用于什么场景。并且这本Docker的学习权威指南介绍了其组件的基础知识,然后用Docker构建容器和服务来完成各种任务:利用Docker为新项目建立测试环境,演示如何使用持续集成的工作流集成Docker,如何构建应用程序服务和平台,如何使用Docker的API,如何扩展Docker。

总共包含了:简介、安装Docker、Docker入门、使用Docker镜像和仓库、在测试中使用Docker、使用Docker构建服务、使用Fig编配Docke、使用Docker API、获得帮助和对Docker进行改进等9个章节的知识。

[外链图片转存中…(img-mqFlDnoJ-1711390957113)]

[外链图片转存中…(img-PTXAj4Hf-1711390957113)]

[外链图片转存中…(img-mnMlba9Y-1711390957114)]

[外链图片转存中…(img-vUkRkOhT-1711390957114)]

关于阿里内部都在强烈推荐使用的“K8S+Docker学习指南”—《深入浅出Kubernetes:理论+实战》、《权威指南-第一本Docker书》,看完之后两个字形容,爱了爱了!
需要更多Java资料的小伙伴可以帮忙点赞+关注,点击传送门,即可免费领取!

  • 8
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
很抱歉,我无法提供完整的Java笔试题大全答案。但是,我可以为您提供一些常见的Java笔试题类型和一些参考答案,希望对您有所帮助。 1. Java基础知识 Q:Java中的八种基本类型是什么? A:byte、short、int、long、float、double、char、boolean。 Q:什么是Java中的自动装箱和拆箱? A:自动装箱是指将基本类型自动转换为相应的包装类型,拆箱则是将包装类型自动转换为相应的基本类型。例如: ``` int a = 123; Integer b = a; // 自动装箱 int c = b; // 自动拆箱 ``` 2. 面向对象编程 Q:什么是Java中的抽象类和接口?它们有什么区别? A:抽象类是一个不能被实例化的类,它的存在只是为了被子类继承。抽象类可以包含抽象方法和非抽象方法。接口是一组方法的集合,没有实现的方法,只有方法的签名,需要实现该接口的类来实现这些方法。 区别在于,抽象类可以包含成员变量和非抽象方法,而接口只能包含常量和抽象方法。另外,一个类只能继承一个抽象类,但是可以实现多个接口。 Q:Java中的多态是什么? A:多态是指同一种行为具有多种不同的表现形式或形态。在Java中,多态可以通过继承和接口来实现。例如: ``` class Animal { void makeSound() { System.out.println("Animal"); } } class Dog extends Animal { void makeSound() { System.out.println("Dog"); } } Animal a = new Dog(); a.makeSound(); // 输出Dog ``` 3. 异常处理 Q:Java中的异常分为哪些类型? A:Java中的异常分为受检异常和非受检异常两种类型。受检异常是指必须在方法声明中声明并处理的异常,例如IOException和SQLException;非受检异常是指RuntimeException及其子类,通常是由程序错误导致的异常,例如NullPointerException和ArrayIndexOutOfBoundsException。 Q:Java中的异常处理机制是什么? A:Java中的异常处理机制包括try-catch-finally语句和throw语句。try块中包含可能抛出异常的代码,catch块用于捕获异常并处理异常,finally块中的代码总是会被执行。throw语句用于手动抛出异常。例如: ``` try { // 可能会抛出异常的代码 } catch (Exception e) { // 处理异常 } finally { // 始终会执行的代码 } ``` 以上是一些常见的Java笔试题类型和参考答案,希望能够帮助您。但是请注意,在面试或者笔试中,考官可能会根据您的回答提出更深入的问题,所以最好还是对Java的各个方面有一个全面的了解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值