中国系统java开发面试准备

面向对象的三大特征以及简单解释:

中国系统java开发面试准备_第1张图片
封装:也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。

继承:它可以使用现有类的所有功能,并且在无需重新编写原来的类的情况下对这些功能进行扩展。通过继承创建的类称为子类或者派生类。被继承的类称为基类、父类或者超类。继承的过程就是从一般到特殊的过程。要实现继承,可以通过继承和组合来实现。通常情况下,一个子类只能继承一个父类,要实现多重继承,可以通过多级继承来实现。

多态:多态性是允许你将父对象设置称为和一个或更多的它的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。简单的说,就是允许将子类类型的指针赋值给父类类型的指针。
实现方式分为重载和覆盖:
覆盖:是指子类重新定义父类的虚函数的做法。
重载:是指允许存在多个同名函数,但这些函数的参数不同。

重写和重载,返回值不同是重载吗?

(1)重写就相当于子类继承自父类的相同方法,输入数据一样,但要做出有别与父类的响应,重载就是同样的一个方法能够根据输入数据的不同,做出不同的处理。
(2)重写发生在子类,参数列表不能修改。重载发生在同一个类中,方法名必须相同,参数类型不同、个数不同、顺序不同。
(3)重写发生在运行期,重载发生在编译期。
重写的注意事项:访问修饰符范围不能变小,异常不能更广。
返回值不同不是重载。

值传递、引用传递的区别

(1)值传递:将原始变量的内容复制下来,再用一个新的内存空间来保存,两个变量之间相互独立,函数范围内对值的任何改变在函数外部都会被忽略。
(2)引用传递:给当前变量起了一个别名,实际上这两个变量引用的是同一个值,函数范围内对值的任何改变在函数外部也能反映出这些修改,它们指向的是同一内存空间。

jdk,jvm,jre的区别和联系,哪个提供垃圾回收

(1)JVM是运行Java字节码的虚拟机,针对不同系统的特定实现
(2)JDK是Java开发工具包,能够创建和编译程序,它拥有jre所拥有的一起,还有编译器(javac)和工具(如:javadoc和jdb)
(3)JRE是java运行时的环境,它是运行已编译JAVA程序所需要的所有内容的集合,包括JVM,Java类库,java命令和其他的一切基础构建,但是并不能用来创建新程序。

hashMap和hashTable

(1)从线程安全的角度来讲,hashmap线程更加安全,hashtable线程不安全(如果要保证线程安全的话就使用ConcurrentHashMap)
(2)效率角度:hashMap要比HashTable效率要高一些
(3)对null的支持:hashmap中null可以作为键,这样的键只有一个,可以有一个或者多个键所对应的值为null。但是在HashTable中put进入的键值只要有一个null,直接抛出空指针异常。
(4)初始容量大小和每次扩充容量大小的不同。
创建时若不指定容量初始值,Hashtable默认值初始大小为11,之后的每次扩充容量变为原来的2n + 1,HashMap默认的初始化大小为16,之后每次扩充,容量变为原来的两倍。
若创建时给定了容量初始值,那么HashTable会直接使用你给定的大小,而HashMap会将其扩充为2的幂次方大小。
(5)底层数据结构不同,JDK1.8以后的HashMap,当链表长度大于阈值(默认为8)时转化为红黑树。Hashtable没有这样的机制。

什么是红黑树

红黑树是一棵二叉搜索树,它在每个节点增加了一个存储位用来记录节点的颜色,可以使红色,也可以是黑色。通过任意一条从根到叶子节点简单路径上的约束,红黑树保证最长路径不超过最短路径的两倍,因而近似平衡。
具体性质如下:
(1)每个节点不是黑色,就是红色。
(2)根节点是黑色的
(3)如果一个节点是红色,那么它的两个子节点就是黑色的(没有连续的红节点)
(4)对于每个节点,从该节点到其后代叶节点的简单路径上,均包含相同数目的黑色节点。

list和set的区别:

(1)list方法可以允许重复的对象,而set方法不允许重复的对象。
(2)list可以插入多个null元素,而set只允许插入一个null元素。
(3)list是一个有序的容器,保证了每个元素的插入元素,即输出顺序就是输入顺序,而set方法就是无序容器,无法保证每个元素的存储顺序,TreeSet通过Comparable接口或者omparator维护了一个排序顺序。
(4)list方法常用的实现类有ArrayList、LinkedList和Vector。Set方法中主要的几个实现类是HashSet、LinkedHashSet以及TreeSet。
(5)List适合经常追加数据,插入删除数据,但随机取值效率较低,Set适合经常的随机存储、插入、删除。但是在遍历时的效率比较低。

线程的状态和转换过程

(1)New:当程序使用new关键字创建了一个线程之后,该线程就属于新建状态。
(2)Runnable:当线程对象调用了start()方法过后,该线程处于就绪状态。
(3)Running Man:如果处于就绪状态的线程获取了CPU,开始执行run()方法的线程执行体,则该线程处于运行状态。
(4)Block:当处于运行状态的线程失去了所占用的资源后,便进入了阻塞状态。
(5)Dead:运行结束、stop()、异常
详细介绍

sleep():使得当前线程进入停滞状态(阻塞当前进程),让出CPU的使用、目的是不让当前进程独自霸占该进程所获得的CPU资源,以留下一定时间给其他进程执行的机会。

java中sleep()和wait()区别

1.sleep方法是Thread类的静态方法,wait()是Object超类的成员方法。
2.sleep()方法导致了程序暂停执行,让出cpu给其他线程,但是他的监控状态依然保持,当指定的时间到了又会自动恢复运行状态。在调用sleep方法的过程中,线程不会释放对象锁。
而当调用wait()的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify方法后本线程才能进入对象锁定池准备。
3.sleep方法需要抛异常,wait方法不用
4.sleep方法可以在任何地方使用,wait方法只能在同步方法和同步代码块中使用
中国系统java开发面试准备_第2张图片
注意sleep方法是单线程的,没有释放锁,这个锁指的是线程锁,不是对象锁,而wait方法释放锁,这个锁是对象锁,所以sleep时间到和wait等到notify之后享受的待遇一样,都是回到就绪状态,等待系统分配cpu

JVM的划分

中国系统java开发面试准备_第3张图片
首先java源代码文件(.java后缀)会被java编译器编译为字节码文件(.class后缀),然后由JVM中的类加载器加载各个类的字节码文件,加载完毕之后,交由JVM执行引擎执行。在整个程序执行过程中,JVM会用一段空间来存储程序执行期间需要用到的数据和相关信息,这段空间一般被称作为Runtiome Data Area(运行时数据区),也就是我们常说的JVM内存。
运行时的数据区通常包括这几个部分:程序计数器(Program Counter Reigster)、Java栈(VM Stack)、本地方法栈(Native Method Stack)、方法区(Method Area)、堆(Heap)。
(1)程序计数器:保存程序当前执行的指令的地址,当CPU需要执行指令时,需要从程序计数器中得到当前需要执行的指令所在存储单元的地址,然后根据的到底地址获取指令,在得到指令之后,程序计数器+1或者根据转移指针得到吓一跳指令的地址,如此循环直到执行完所有指令。在JVM中,程序计数器是每个线程所私有的,若线程执行的是非native方法,则程序计数器中保存的是当前需要执行指令的地址,如果线程执行的是native方法,则程序计数器中的值是undefined。
(2)Java栈:是Java方法执行的内存模型,java栈中存放的是一个个的栈帧,每个栈帧第一把那个一个被调用的方法,在栈帧中包括局部变量表、操作数栈、指向当前方法所属的类的运行时常量池的引用、方法返回地址、额外的附加信息。
(3)本地方法栈:与Java栈的区别为Java栈是为执行Java方法服务的,而本地方法栈则是为执行本地方法服务的。
(4)堆:Java中的堆是用来存储对象本身以及数组(数组引用存放在Java栈中)。在java中,程序员基本不用关心空间释放的问题,Java的垃圾回收机制会进行自动处理。另外,堆被所有的线程所共享,在JVM中只有一个堆。
(5)方法区:被线程共享,在方法区中,存储了每个类的信息(包括类的名称、方法信息、字段信息)、静态变量、常量以及编译器编译后的代码。在方法区中有一个非常重要的部分就是运行时常量池,它是每一个类或接口的常量池的运行时表示形式,在类和接口被加载到JVM中后,对应的运行常量池就会被创建出来。当然并非Class文件常量池中的内容才能进入运行时常量池,在运行期间也可将新的常量放入运行时常量池中。

JIT即时编译

just in time的缩写,即时编译技术,在运行时JIT会把编译过得机器码保存起来,以备下次使用,使用JIT能够加速Java程序的执行速度。
JIT编译(just-in-time compilation)狭义来说是当某段代码即将第一次被执行时进行编译,因而叫“即时编译”。JIT编译是动态编译的一种特例。
一个程序在它运行的时候创建并且运行了全新的代码,而并非那些最初作为这个程序的一部分保存在硬盘上的固有的代码。就叫 JIT。
几个重点:
(1)程序需要运行
(2)生成的代码是新的代码,并非作为原始程序的一部分被存在磁盘上的那些代码。
(3)不光生成代码,还要运行新的代码。

垃圾回收算法:CMS

首先,JVM GC只回收堆区和方法区内的对象。而栈区的数据,在超出作用域后会被JVM自动释放掉,与JVM GC无关。
JVM GC怎么判断对象可以被回收了?
(1)对象没有引用
(2)作用域发生位捕获异常
(3)程序在作用域正常执行完毕
(4)程序执行了System.exit()
(5)程序发生意外终止(例如被杀线程)

新生代:绝大多数最新被创建的对象都会被分配到这里,由于大部分在创建后很快变得不可达,很多对象被创建在新生代,然后消失。
老年代:对象没有变得不可达,而且从新生代周期中存活了下来,会被拷贝到这里。
吃就嗲:也被称为方法区:用于保存常量以及字符串常量。这个区域的的发生GC的条件非常严苛,必须符合以下三个条件:
(1)所有实例被回收
(2)加载该类的ClassLoader被回收
(3)Class对象无法荣国任何途径访问,包括反射

JVM GC算法讲解

1、根搜索算法:程序将所有引用关系看做一张图,从一个节点GC ROOT开始,寻找对应的引用节点,找到这个节点后,继续寻找这个节点的引用节点。当所有的应用节点寻找完毕后,剩余的节点被认为是无用节点。
2.标记-清除算法:标记清除算法从根集合进行扫描,对存活的对象进行标记,标记完毕后,再扫描整个空间未被标记的对象进行回收。
3.复制算法:将内存分为两个区,使用此算法时,所有动态分配的对象都只能分配在其中一个区间(活动区间),而另一个区间(空闲区间)则是空闲的。
4.标记-整理算法:在标记清除算法的基础上,又进行了对象的移动排序整理,因此成本更高,但解决了内存碎片的问题。

CMS(Concurrent MarkSweep)是以牺牲吞吐量为代价来获得最短回收停顿时间的垃圾回收器,是一个老年代回收器。它是对于响应时间的重要性需求大于吞吐量要求的收集器。对于要求服务器响应素的高的情况下,使用CMS非常合适。 CMS的一大特点就是用两次短暂的暂停来替代串行或者并行标记整理算法中的长暂停。
使用算法:标记-整理算法。

CMS使用场景:GC过程短暂停,适合对时延要求较高的服务,用户线程不允许长时间的停顿。

CMS的执行过程

初始标记:此时虚拟机停顿正在执行的应用线程,这个过程从根对象扫描直接关联的对象,并作标记。
并发标记:这个阶段紧随初始标记阶段,在初始标记的基础上继续向下回溯标记,并发表示GC线程和用户线程一起执行,不用暂停用户线程。
并发预清理:jvm查找正在执行并发标记阶段时候进入老年代的对象。
重新标记:再次暂停正在执行的应用线程,重新从根对象开始查找并标记并发阶段遗漏的对象,并处理对象关联。
并发清理:这个阶段是并发的,应用线程和GC线程可以一起并发执行。
并发重置:这个阶段重置CMS收集器的数据结构,等待下一次垃圾回收。

CMS的缺点

(1)内存碎片:由于使用了标记-清理算法,导致内存空间中会产生内存碎片。
(2)需要更多的cpu资源,由于使用了并发处理,这样就是需要更多的cpu资源,也是牺牲了一定吞吐量的原因。
(3)需要更大的堆空间,因为CMS标记阶段应用程序的线程还是执行的,那么就会有堆空间继续分配的问题。

内存泄漏和内存溢出的区别

内存溢出:out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,出现内存溢出,比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出。
内存泄漏:是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄漏可以忽略,但内存泄漏堆积后果很严重,无论多少内存,迟早被占用干净。
内存泄漏会导致内存溢出。

三次握手,四次挥手的过程

三次握手:
发送方:同步请求信号SYN=1,序列号seq=x;
接收方:SYN=1,确认号ACK=1,ack=x + 1,seq=y
发送方:SYN=1,ACK=1,ack=y + 1,seq = x + 1
原因:避免已经失效的连接请求报文发送给对方,引起错误

四次挥手:
发送方:FIN终止信号=1,seq=u
接收方:ACK=1,ack=u+1,seq=v
接收方:FIN=1,ack= u + 1,seq = w;
发送方:ACK=1,ack = w + 1,seq = u +1;
TCP是全双工模式,这就意味着,当主机1发出FIN报文段时,只是表示主机1已经没有数据要发送了,主机1告诉主机2,它的数据已经全部发送完毕了,但是这个时候主机1还可以接受来自主机2的数据;当主机2收到ACK报文段时,表示它已经知道主机1没有数据发送了,但是主机2还可以发送数据到主机1的,当主机2也发送了FIN报文段时,这个时候就表示主机2也没有数据要发送了,就是告诉主机1没有要发送的数据了。

http是哪一层?常用状态码?301是?

应用层;1开头表示正在处理,2开头表示请求已经正确处理,3开头表示需要进行附加操作例如重定向,4开头表示客户端错误导致服务器无法处理,5开头表示服务器错误。
301 redirect: 301 代表永久性转移(Permanently Moved)
302 redirect: 302 代表暂时性转移(Temporarily Moved )
401 : (未授权)当前请求需要用户验证。
404 : (未找到)请求失败,请求的数据在服务器上未发现。
301表示永久性重定向,请求的资源已经被永久的刷新到新的URL,返回信息会包含新的URL,浏览器会自动定向到新URL。今后的任何新的请求都会使用新的URL代替。

301与302的区别

301和302状态码都表示重定向,就是说浏览器在拿到服务器返回的这个状态码后会自动跳转到一个新的URL地址,这个地址可以从响应的Location首部中获取(用户看到的效果就是他输入的地址A瞬间变成了另一个地址B)——这是它们的共同点。他们的不同在于。301表示旧地址A的资源已经被永久地移除了(这个资源不可访问了),搜索引擎在抓取新内容的同时也将旧的网址交换为重定向之后的网址;302表示旧地址A的资源还在(仍然可以访问),这个重定向只是临时地从旧地址A跳转到地址B,搜索引擎会抓取新的内容而保存旧的网址。

数据库中的锁都会有哪些种类?什么情况引起表锁?

从数据库的角度可以分为共享锁,排他锁,更新锁。
从程序员角度可分为乐观锁和悲观锁。
悲观锁:每次去使用数据时都认为别人会修改,所以每次在拿数据时都会上锁,这样别人若想使用该数据就会被阻塞,直到他拿到锁。传统的关系数据库中常用到悲观锁,例如行锁、表锁、读锁、写锁,都是在操作之前先上锁。
悲观锁也可分为:
(1)共享锁,S锁,也叫读锁,用于所有的只读数据操作。共享锁是非独占的,允许多个并发事务读取其锁定的资源。性质:多个事务可以封锁同一个共享页;任何事务都不能修改该业;通常该页被读取完毕,S锁立即被释放。
(2)排他锁:X锁,也叫写锁,表示对数据进行写操作。如果一个事务对独享加了排他锁,其他事务就不能再给它加任何锁了。性质:仅允许一个事务封锁此页;其他任何事务必须等到X锁被释放才能对该页进行访问;X锁一直到事务结束才能被释放。
(3)更新锁:U锁,在修改操作的初始化阶段用来锁定可能要被修改的资源,这样可以避免使用共享锁造成的死锁现象。性质:用来预定要对此页市价X锁,它允许其他事物读,但不允许再施加U锁或者X锁;当被读取的页要被更新时,则升级为X锁;U锁一直到事务结束时才能被释放。

乐观锁:每次去拿数据的时候都认为别人不会修改,所以不会上锁。但是在更新的时候会判断一下在此期间别人有没有更新这个数据,可以使用版本号等机制。乐观锁使用于多读的类型,这样可以提高吞吐量。
乐观锁的实现方式:(1)版本号(2)时间戳(3)待更新字段(4)所有字段

表锁:
锁的作用范围是整张表,数据库能够确定哪些行需要锁的情况下使用行锁,如果不知道会影响哪些行的时候就会使用表锁。

事务的特性

事务是应用程序中一系列逻辑操作相关的操作,所有操作必须全部完成,否则在每个操作中所做的所有更改都会被撤销。
原子性:原子性要求每个事务中的所有操作要么都完成,要么就像全部都没有发生一样,如果事务中的部分操作失败了,那么整个事务都失败了。
一致性:一致性确保了任何事务都会是数据库从一种合法的状态转变为另一种合法的状态。
隔离性:保证了并发执行多个事务对系统的状态的影响和串行化执行多个事务对系统的状态影响是一样的。
持久性保证了一个事务一旦被提交了以后,其状态就保持不变,即使发生了主机断电、崩溃、错误等情况。

脏读、幻读、不可重复读

1.脏读是指一个事务已经访问了数据,并且修改了数据,而这种修改还没有提交到数据库中,此时另外一个事务也访问了该数据,并且修改了这个数据。
2.不可重复读:是指在一个事务内,多次读同一数据,而这个事务还没有结束时,另外一个事务也访问了该数据。那么再第一个事务的两次读取时,由于第二个事务的修改,那么第一个事务两次读取到的数据可能不一样。
3.幻读:指事务不是独立执行时发生的一种现象,例如第一个事务对表中的数据进行了修改,这种修改设计表中的全部数据行,同时第二个事务也修改了这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还没有被修改的数据行,就像发生幻觉一样。

事务的隔离级别

读未提交:就是一个事务可以读取另一个未提交事务的数据
读提交:就是一个事务要等另一个事务提交后才能读取数据
重复读:就是在开始读取数据(事务开启)时,不再允许修改操作。避免脏读和不可重复读。默认隔离级别。
序列化(可串行化):是最高的事务隔离级别,在该级别下,事务串行化顺序执行,可以避免脏读、不可重复读和幻读。但是这种事务隔级别的效率低下、比较消耗数据库性能,一般不使用。

TCP为什么是可靠的?

(1)校验和:TCP的校验和是必须的,而UDP的校验和是可选的。
(2)序列号:TCP的每个字节都有自己的序列号,序列号的作用为:保证可靠性;保证数据的按时到达、提高效率,实现多次发送、一次确认;去除重复数据、
(3)确认应答机制:ACK:TCP通过去人应答的机制实现可靠的传输,接收方对于按序到达的字段进行确认,若有效,则发送ACK = 1,而发送方收到了确认报文后才能进行下一次的数据传输,否则等待一段时间后进行重传。
(4)超时重传机制:当发送方发送报文一段时间后还没有收到确认应答,发送方进行重传。
(5)连接管理机制:三次握手,四次挥手。
(6)拥塞控制(慢启动):拥塞窗口:发送方开始定义拥塞窗口为1,每收到一个ack应答,拥塞窗口+1,而发送窗口取拥塞窗口和接收窗口的最小值。
慢启动:在启动初期以指数方式增长,收到确认段超时,设置一个慢启动的阈值为拥塞窗口的一半,设置拥塞窗口为1,重新慢启动,达到阈值后为线性增加。收到连续三次确认回答后,启动快速重传,将阈值设为拥塞窗口的一半,拥塞窗口设置为阈值大小。
(7)流量窗口:接收方将自己可以接受的缓冲区大小放入TCP首部的窗口大小字段,通过ACK发送给发送端。

UDP的特征,应用

UDP协议被广泛用到对网络数据传输的实时性很高,对数据准确性不是非常高的场合,语音,视频。
1.UDP是无连接的,即发送结束时也没有连接需要释放,因而减小的开销和发送时的时延。
2.UDP采用最大努力交付,不保证可靠交付。
3.UDP是面向报文的,只把应用层交下来的报文增加首部后就交给网络层。
4.UDP是无拥塞控制的,即网络中存在阻塞,也不影响发送端的发送频率。
5.UDP支持一对一,一对多,多对一,多对多的交互通信。
6.UDP的首部开销小,相对于TCP的20个字节只要8个字节。

你可能感兴趣的:(中国系统java开发面试准备)