基础篇
1.面向对象和面向过程的区别
面向过程的实现更简单,所以在简单程序的运行来说,性能是优于面向对象的。对于简单的程序来说,可以快速的实现,面向对象的编程相对来说,要实现的步骤比更复杂一点,要先从类开始设计,还要定义类如何生成对象,但是面向对象的程序容易扩展,容易维护,易复用的优点,而且更加贴近现实世界。
另外,设计糟糕的面向过程的程序有时性能并不见得一定优于面向对象的编程,而面向对象的程序可以通过优化,接近面向过程的程序的性能。
2.Java 语言有哪些特点?
1).简单易学; Java简化了C语言很多复杂难懂的操作,所以简单易学。
2).面向对象 (封装,继承,多态) ;
3).平台无关性 ( Java 虚拟机实现平台无关性) ;在Windows和Linux上都可以使用
4).可靠性; 可以平稳,持续的运行
5).安全性; 内存被严格管理,利用虚拟机是使程序与操作系统隔离。
6).支持多线程。Java程序支持并发执行,充分利用CPU。
7).支持网络编程并且很方便(Java 语言诞生本身就是为简化网络编程设计的,因此Java 语言不仅支持网络编程而且很方便) :
8).编译与解释并存;
3.字符型常量和字符串常量的区别?
- 形式上: 字符常量是单引号引起的一个字符; 字符串常量是双引号引起的若干个字符
- 含义上: 字符常量相当于一个整型值( ASCII 值),可以参加表达式运算;字符常量代表一个地址值(该字符串在内存中存放位置)
- 占内存大小 字符常量只占 2 个字节; 字符串常量占若个字节(注意: char 在Java 中占两个字节)
4.构造器 Constructor 是否可被 override?
Constructor 不能被 override (重写),但是可以overload (重载),所以你可以看到一个类中有多个构造函数的情况
4.接口和抽象类的区别是什么?
1.接口的方法默认是 public,所有方法在接口中不能有实现(ava 8 开始接口方法可以有默认实现)而抽象类可以有非抽象的方法。
2.接口中除了 static、final变量,不能有其他变量,而抽象类中则不一定。
3.一个类可以实现多个接口,但只能实现一个抽象类。接口自己本身可以通过 extends 关键字扩展多个
接口。
4.接口方法默认修饰符是 public,抽象方法可以有 public、proteted 和 default 这些修饰符 (抽象方法就是为了被重写所以不能使用 private 关键字修饰 !)
5.从设计层面来说,抽象是对类的抽象,是一种模板设计,而接口是对行为的抽象,是一种行为的规范。
5.构造方法有哪些特性?
1.名字与类名相同。
2.没有返回值,但不能用 void 声明构造函数。3.生成类的对象时自动执行,无需调用
6.简述线程、程序、进程的基本概念。以及他们之间关系是什么?
线程与进程相似,但线程是一个比进程更小的执行单位。一个进程在其执行的过程中可以产生多个线程。与进程不同的是同类的多个线程共享同一块内存空间和一组系统资源,所以系统在产生一个线程,或是在各个线程之间作切换工作时,负担要比进程小得多,也正因为如此,线程也被称为轻量级进程。
程序是含有指令和数据的文件,被存储在碰盘或其他的数据存储设备中,也就是说程序是静态的代码。
进程是程序的一次执行过程,是系统运行程序的基本单位,因此进程是动态的。系统运行一个程序即是个进程从创建,运行到消亡的过程。简单来说,一个进程就是一个执行中的程序,它在计算机中一个指令接着一个指令地执行着,同时,每个进程还占有某些系统资源如 CPU 时间,内存空间,文件,输入输出设备的使用权等等。换句话说,当程序在执行时,将会被操作系统载入内存中。 线程是进程划分成的更小的运行单位。线程和进程最大的不同在于基本上各进程是独立的,而各线程则不一定,因为同一进程中的线程极有可能会相互影响。从另一角度来说,进程属于操作系统的范畴,主要是同一段时间内,可以同时执行一个以上的程序,而线程则是在同一程序内几乎同时执行一个以上的程序段。
7.BIO,NIO,AIO 有什么区别?
BIO(Blocking I/O): 同步阻塞 I/O 模式,数据的读取写入必须阻塞在一个线程内等待其完成。在活动连接数不是特别高 (小于单机 1000) 的情况下,这种模型是比较不错的,可以让每一个连接专注于自己的 I/O 并且编程模型简单,也不用过多考虑系统的过载、限流等问题。线程池本身就是一个天然的漏斗,可以缓冲一些系统处理不了的连接或请求。但是,当面对十万甚至百万级连接的时候,传统的 BIO 模型是无能为力的。因此,我们需要一种更高效的I/O 处理模型来应对更高的并发量。
NIO(New I/O): NIO 是一种同步非阻塞的I/O 模型,在Java 1.4 中引入了 NIO 框架,对应ava.nio包,提供了 Channel,Selector,Buffer 等抽象。NIO 中的 N 可以理解为 Non-blocking,不单纯是New。它支持面向缓冲的,基于通道的I/O 操作方法。NIO 提供了与传统 BIO 模型中的 Socket 和serverSocket 相对应的 SocketChannel和 ServerSocketChannel 两种不同的套接字通道,实现两种通道都支持阻塞和非阻塞两种模式。阻塞模式使用就像传统中的支持一样,比较简单,但是性能和可靠性都不好:非阻塞模式正好与之相反。对于低负载、低并发的应用程序,可以使用同步阻塞 I/O来提升开发速率和更好的维护性:对于高负载、高并发的(网络)应用,应使用 NIO 的非阻塞模式来开发。
AIO(Asynchronous I/0): AIO 也就是 NIO2。在Java 7 中引入了 NIO 的改进版 NIO 2,它是异步非阻塞的 IO 模型。异步I/O 是基于事件和回调机制实现的,也就是应用操作之后会直接返回,不会堵塞在那里,当后台处理完成,操作系统会通知相应的线程进行后续的操作。AIO 是异步 IO 的缩写,虽然 NIO 在网络操作中,提供了非阻塞的方法,但是 NIO 的 IO 行为还是同步的。对于 NIO 来说我们的业务线程是在 IO 操作准备好时,得到通知,接着就由这个线程自行进行IO 操作,IO 操作本身是同步的。查阅网上相关资料,我发现就目前来说 AIO 的应用还不是很广泛,Netty 之前也尝试使用过 AIO,不过又放弃了。
Java集合
1.说说List,Set,Map三者的区别?
List(对付顺序的好帮手): List接口存储一组不唯一 (可以有多个元素引用相同的对象),有序的对象
Set(注重独一无二的性质): 不允许重复的集合。不会有多个元素引用相同的对象。
Map(用Key来搜索的专家): 使用键值对存储。Map会维护与Key有关联的值。两个Key可以引用相同的对象,但Key不能重复,典型的Kev是String类型,但也可以是任何对象。
2. ArrayList 与 Vector 区别呢?为什么要用Arraylist取代Vector呢?
Vector类的所有方法都是同步的。可以由两个线程安全地访问一个Vector对象、但是一个线程访问Vector的话代码要在同步操作上耗费大量的时间。
ArrayList不是同步的,所以在不需要保证线程安全时建议使用ArrayList。
多线程
1.使用多线程可能带来什么问题?
并发编程的目的就是为了能提高程序的执行效率提高程序运行速度,但是并发编程并不总是能提高程序运行速度的,而且并发编程可能会遇到很多问题,比如: 内存泄漏、上下文切换、死锁还有受限于硬件和软件的资源闲置问题。
2.什么是上下文切换?
多线程编程中一般线程的个数都大于 CPU 核心的个数,而一个 CPU 核心在任意时刻只能被一个线程使用,为了让这些线程都能得到有效执行,CPU 采取的策略是为每个线程分配时间片并轮转的形式。当一个线程的时间片用完的时候就会重新处于就绪状态让给其他线程使用,这个过程就属于一次上下文切换。
概括来说就是: 当前任务在执行完 CPU 时间片切换到另一个任务之前会先保存自己的状态,以便下次再切换回这个任务时,可以再加载这个任务的状态。任务从保存到再加载的过程就是一次上下文切换。
上下文切换通常是计算密集型的。也就是说,它需要相当可观的处理器时间,在每秒几十上百次的切换中,每次切换都需要纳秒量级的时间。所以,上下文切换对系统来说意味着消耗大量的 CPU 时间,事实上,可能是操作系统中时间消耗最大的操作。
Linux 相比与其他操作系统 (包括其他类 Linux 系统)有很多的优点,其中有一项就是,其上下文切换和模式切换的时间消耗非常少。
3.什么是线程死锁?如何避免死锁?
学过操作系统的朋友都知道产生死锁必须具备以下四个条件:
1. 互斥条件: 该资源任意一个时刻只由一个线程占用。
2. 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
3.不剥夺条件:线程已获得的资源在末使用完之前不能被其他线程强行剥夺,只有自己使用完毕后才释放资源。
4.循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
如何避免线程死锁?
我们只要破坏产生死锁的四个条件中的其中一个就可以了
破坏互斥条件
这个条件我们没有办法破坏,因为我们用锁本来就是想让他们互斥的(临界资源需要工斥访问)。
破坏请求与保持条件
一次性申请所有的资源。
破坏不剥夺条件
占用部分资源的线程进一步申请其他资源时,如果申请不到,可以主动释放它占有的资源。
破坏循环等待条件
靠按序申请资源来预防。按某一顺序申请资源,释放资源则反序释放。破坏循环等待条件,