Java春招面试核心考点附带解析
ip地址和mac地址的区别
首先ip地址是逻辑地址,mac地址是物理地址,mac地址具有唯一性,ip地址不具备唯一性。
用一句话概括两者的区别就是:二层基于mac地址转发数据帧,三层基于ip地址转发报文
简单说一下arp协议
arp为地址解析协议。作用是在以太网环境中,数据传输所依赖的是mac地址而非ip地址,arp协议就是将已知ip地址转换为mac地址
arp动态映射中,每次只要机器知道另一台机器的逻辑(ip)地址,就可以使用协议找出对应的物理地址
arp原理及流程:首先在主机与主机之间,一台主机要知道接收方的逻辑(ip)地址才能将ip数据报文发送给另一台主机,但是ip地址必须封装成帧才能通过物理网络,发送方必须有接收方的物理(mac)地址,从而要完成逻辑地址到物理地址的映射,而arp地址协议可以接受来自ip协议的逻辑地址,将其映射为相应的物理地址,然后把解析后的物理地址递交给数据链路层
TCP和UDP的区别
-
TCP(传输控制协议)是面向连接的协议,也就是说发送数据需要建立复杂的连接,UDP(用户数据报协议)是无连接的,发送数据不需要建立连接
-
TCP提供交付保证,(因为它存在通过校验和,传输控制,序列标识,滑动窗口,确认应答实现可靠传输),TCP提供有序,无差错,不丢失,不重复的性质,而UDP尽最大努力交付,它是无序的,他的任务就是尽最大可能的传输数据,其他的不搞,同时,TCP的逻辑通信信道是全双工的可靠信道,UDP则是不可靠信道,它为什么不可靠,就是因为它只管交付成功其他的不管。
-
UDP的工作效率高,且具有较好的实时性,它比较适合对于高速传输,点击率高,实时性高的通信或广播通信,TCP对于网络质量有要求,适用于HTTP,HTTPS,FTP传输文件协议,POP,MOT等邮件传输协议
-
TCP首部开销20字节,UDP首部8个字节
-
TCP速度慢,因为它必须建立复杂的连接,保证消息的可靠性和有序性,UDP的速度就很快,它只管尽最大努力交付
-
UDP没有拥塞控制,所以当网络出现拥塞的时候也不会是源主机发送速率降低,TCP是有拥塞控制的
-
TCP面向字节流,UDP是面向报文的
-
TCP是重量级协议,因为它传输信息不但要创造连接,且保证有序性,所以它对系统资源要求较多,UDP只管尽最大努力交付,不用做其他的,所以它对系统资源要求较少,是一个轻量级的协议
-
每一条TCP连接只能是点到点,UDP支持一对一,一对多,多对一,和多对多的交互通信,因为基于UDP不需要建立连接,使用与多播的环境
三次握手和四次挥手原理
三次握手:首先通俗的来讲三次握手,第一次:客户端向服务器发送数据包:“我想给你发数据,可以吗”,第二次:服务器向客户端发送同意连接和要求同步:“可以的,那你什么时候发呢?”,第三次:客户端在发出一个数据包确认服务器的要求同步:“那我现在就发,你准备好接着哦~,只有经过这三次之后,客户端才向服务器正式发送数据
正式三次握手细节:服务端新建套接字,绑定地址信息后开始监听,进入LISTEN状态。客户端新建套接字绑定地址信息后调用connect,发送连接请求SYN(同步序列号),并进入SYN_SENT状态,等待服务器的确认。服务端一旦监听到连接请求,就会将连接放入内核等待队列中,并向客户端发送SYN(同步序列号)和确认报文段ACK(确认应答),进入SYN_RECD状态。客户端收到SYN(同步序列号)+ACK(确认应答)报文后向服务端发送确认报文段ACK(确认应答),并进入ESTABLISHED状态,开始读写数据。服务端一旦收到客户端的确认报文,就进入ESTABLISHED状态,就可以进行读写数据了。
为什么TCP握手是三次呢
首先两次不安全,四次没有必要,tcp要确保双发都具有收发能力,得到ACK(确认应答)相应则认为对方具有数据收发的能力,因此双发都要发送SYN确保对方具有通信能力。
第一次握手:客户端,发送SYN,服务端接受,服务端得出客户端的发送能力和服务端的接收能力正常,这次握手是不可以携带数据的
第二次握手:服务端发送SYN+ACK,客户端接收,客户端得出客户端发送接收能力正常,服务端发送接收能力也正常,这一次的握手也是不可以携带数据的
第三次握手:为什么还要第三次呢,以为此时服务器并不能确认客户端的接收能力是否正常,这次客户端发送ACK,服务器接收,服务端才能得出客户端发送接收能力正常,服务端自己发送接收能力也都正常,之后就建立了链接,就可以传输数据,但是第三次握手是可以携带数据的,为什么之前两次握手不可以携带数据呢,因为在第一次握手可以携带数据,如果此时有人恶意攻击服务器,每一次都在第一次握手中的SYN报文放入大量数据,重复发送大量SYN报文,此时服务器会花费大量内存空间来缓冲这些报文,服务器就更容易被攻击了
四次挥手:客户端主动调用close时,向服务端发送结束报文段FIN报,同时进入FIN_WAIT1状态;服务器会收到结束报文段FIN报,服务器返回确认报文段ACK并进入CLOSE_WAIT状态,此时如果服务端有数据要发送的话,客户端依然需要接收。客户端收到服务器对结束报文段的确认,就会进入到FIN_WAIT2状态,开始等待服务器的结束报文段;服务器端数据发送完毕后,当服务器真正调用close关闭连接时,会向客户端发送结束报文段FIN包,此时服务器进入LAST_ACK状态,等待最后一个ACK的带来;客户端收到服务器发来的结束报文段, 进入TIME_WAIT, 并发出送确认报文段ACK;服务器收到了对结束报文段确认的ACK,进入CLOSED状态,断开连接。而客户端要等待2MSL的时间,才会进入到CLOSED状态
第一次:客户端完成数据传输之后,将控制位FIN置1,提出停止TCP连接的请求
第二次:服务端收到FIN后对其做出响应,确认这一方向上的TCP连接将关闭,将ACK置1
第三次:由服务端再提出反方向的关闭请求,将FIN置1
第四次:客户端对服务端的请求进行确认,将ACK置1,双方向的关闭结束
为什么握手要三次而挥手要四次呢
因为在TCP握手的时候,接收端将SYN包和ACK确认包合并到一个包中发送,所以减少了一次包的发送,那为什么挥手要四次呢,因为TCP是全双工通信,要双方向的关闭结束,所以要四次挥手,四次挥手需要四次数据包的交互,一个方向上要服务端和客户端都关闭通信这个方向上才不能传输数据,如果只是一方但方关闭通信,另一方可能还要发送数据,所以就不能将服务端的FIN包和对客户端的ACK包合并发送
public class和class有哪些区别
-
一个java源文件当中可以定义多个class
-
一个java源文件当中public的class不是必须的
-
一个class会定义生成一个xxx.class字节码文件
-
一个java源文件当中定义公开的类的话,public的class只能有一个,并且该类名称必须和java源文件名称一致
-
每一个class当中都可以编写main方法,都可以设定程序的入口,想执行B.class中的main方法:java B
-
注意:当在命令窗口中执行java Hello,那么要求Hello.class当中必须有主方法,没有主方***出现运行阶段的错误
面向过程和面向对象的区别
-
面向过程主要关注的是实现具体过程,因果关系
-
优点:对于业务逻辑比较简单的程序,可以达到快速开发,前期投入成本较低
-
缺点:采用面向过程的开发方式很难解决非常复杂的业务逻辑,另外面向过程的方式导致软件元素之间的“耦合度”非常高,只要其中一环出现问题,整个系统受到影响,导致最终的软件“扩展力”差,另外,由于没有独立体的概念,所以无法达到组件复用
-
-
面向对象,类和对象的概念
-
什么是类:类在现实世界当中是不存在的,是一个模板,是一个概念,是人类大脑思考抽象的结果,类代表了一类事物,在现实世界当中,对象A与对象B之间具有共同特征,进行抽象总结出一个模板,这个模板称为类
-
什么是对象:对象是实际存在的个体,现实世界当中实际存在
-
package和import区别
package包:管理组织代码,包自动形成访问权限的控制,包的本质是文件夹
包的声明:类文件的第一行,类的外部。包的声明和类所在的路径必须要一致
import带入类,可以是具体的一个类,也可以是所有类
简单记忆访问权限
同一个类 | 同一个包 | 子类 | 所有类 | |
---|---|---|---|---|
private | 可以 | |||
default | 可以 | 可以 | ||
protected | 可以 | 可以 | 可以 | |
public | 可以 | 可以 | 可以 | 可以 |
重写和重载
重载:同类同方法名,参数列表
重写:两个类存在父子关系,当父类的方法不能满足子类需求的时候,保持方法名和参数列表必须相同,当子类重写父类的某个方法之后,通过子类调用该方法,一定是重写之后的方法
引用和对象
引用指的是引用类型的变量,存在栈当中
对象指的是根据类模板在堆中开辟的空间
引用指向对象
Child c = new Child();
父类引用可以指向父类与子类对象
子类引用可以指向子类对象
子类引用不能直接指向父类对象
接口和抽象类的区别
首先什么是接口:从本质上讲,接口是一种特殊的抽象类,这种抽象类中只包含常量和方法的定义,而没有变量和方法的实现,从语义上可以理解为,对于某一种动作,行为,功能的抽象,我们将其定义为接口,作为一种标准完全的规范而已,不适宜定义为类
什么是抽象类:分析事物时,发现了共性内容,就出现向上抽取,会有这样一种特殊情况,就是方法功能声明相同,但方法功能主体不同,那么这时也可以抽取,但抽取方法声明,不抽取方法主体,那么此方法就是一个抽象方法
接口和抽象类的区别
-
抽象类可以存在普通成员函数,而接口中只能存在public abstract方法。
-
抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的。
-
抽象类只能继承一个,接口可以实现多个
-
接口是用来对类的形为进行约束。也就是提供了一种机制,可以强制要求所有的类具有相同的形为,只约束了行为的有无,不限制形为的具体实现
-
抽象类是为了代码复用。当不同的类具有相同的行为A,且其中一部分形为B的实现方式一致时,可以让这些类都派生于一个抽象类,这个抽象类中实现了B,避免让所有的子类来实现B,以此来达到代码复用的目的。而A-B的部分,交给各个子类自己实现,正是由于这里A-B的行为没有实现,所以抽象类不允许实例化
SpringMVC和SpringBoot有什么区别
springmvc是一个web框架,他提供了一种轻度耦合的方式来开发web应用
springboot引入了自动配置的概念,实现了自动配置,降低了项目搭建的复杂度,让项目设置变得更加容易,它是一种快速,敏捷的开发新一代spring框架的应用程序
Spring 框架就像一个家族,有众多衍生产品例如 boot、security、jpa等等。但他们的基础都是Spring 的 ioc和 aop ioc 提供了依赖注入的容器 aop ,解决了面向横切面的编程,然后在此两者的基础上实现了其他延伸产品的高级功能。Spring MVC是基于 Servlet 的一个 MVC 框架 主要解决 WEB 开发的问题,因为 Spring 的配置非常复杂,各种XML、 JavaConfig、hin处理起来比较繁琐。于是为了简化开发者的使用,从而创造性地推出了Spring boot,约定优于配置,简化了spring的配置流程。
Spring中Bean的生命周期
实例化Bean
对于BeanFactory容器,当客户向容器请求一个尚未初始化的bean时,或初始化bean的时候需要注入另一个尚未初始化的依赖时,容器就会调用createBean进行实例化。 对于ApplicationContext容器,当容器启动结束后,便实例化所有的bean。 容器通过获取BeanDefinition对象中的信息进行实例化。并且这一步仅仅是简单的实例化,并未进行依赖注入。 实例化对象被包装在BeanWrapper对象中,BeanWrapper提供了设置对象属性的接口,从而避免了使用反射机制设置属性。
设置对象属性
实例化后的对象被封装在BeanWrapper对象中,并且此时对象仍然是一个原生的状态,并没有进行依赖注入。 紧接着,Spring根据BeanDefinition中的信息进行依赖注入。 并且通过BeanWrapper提供的设置属性的接口完成依赖注入。
注入Aware接口
紧接着,Spring会检测该对象是否实现了xxxAware接口,并将相关的xxxAware实例注入给bean。
BeanPostProcessor
当经过上述几个步骤后,bean对象已经被正确构造,但如果你想要对象被使用前再进行一些自定义的处理,就可以通过BeanPostProcessor接口实现。 该接口提供了两个函数:
-
postProcessBeforeInitialzation( Object bean, String beanName ) 当前正在初始化的bean对象会被传递进来,我们就可以对这个bean作任何处理。 这个函数会先于InitialzationBean执行,因此称为前置处理。 所有Aware接口的注入就是在这一步完成的。
-
postProcessAfterInitialzation( Object bean, String beanName ) 当前正在初始化的bean对象会被传递进来,我们就可以对这个bean作任何处理。 这个函数会在InitialzationBean完成后执行,因此称为后置处理。
InitializingBean与init-method
-
afterPropertiesSet()
这一阶段也可以在bean正式构造完成前增加我们自定义的逻辑,但它与前置处理不同,由于该函数并不会把当前bean对象传进来,因此在这一步没办法处理对象本身,只能增加一些额外的逻辑。 若要使用它,我们需要让bean实现该接口,并把要增加的逻辑写在该函数中。然后Spring会在前置处理完成后检测当前bean是否实现了该接口,并执行afterPropertiesSet函数。
当然,Spring为了降低对客户代码的侵入性,给bean的配置提供了init-method属性,该属性指定了在这一阶段需要执行的函数名。Spring便会在初始化阶段执行我们设置的函数。init-method本质上仍然使用了InitializingBean接口。
DisposableBean和destory-method
和init-method一样,通过给destroy-method指定函数,就可以在bean销毁前执行指定的逻辑。
什么是Spring的循环依赖
简单来讲,就是有一个 A 对象,创建 A 的时候发现 A 对象依赖 B,然后去创建 B 对象的时候,又发现 B 对象依赖 C,然后去创建 C 对象的时候,又发现 C 对象依赖 A。这就是所谓的循环依赖。