目录
75. final、finally、finalize 有什么区别?
76. try-catch-finally 中哪个部分可以省略?
77. try-catch-finally 中,如果 catch 中 return 了,finally 还会执行吗?
79. http 响应码 301 和 302 代表的是什么?有什么区别?
08、什么是设计模式?你是否在你的代码里面使用过任何设计模式?
109、Java 中什么叫单例设计模式?请用 Java 写出线程安全的单例模式
110、在 Java 中,什么叫观察者设计模式(observer design pattern)?
113、举一个用 Java 实现的装饰模式(decorator design pattern)?它是作用于对象层次还是类层次?
异常
74. throw 和 throws 的区别?
throw:是真实抛出一个异常。
throws:是声明可能会抛出一个异常。
(1)throw
作用在方法内,表示抛出具体异常,由方法体内的语句处理;
一定抛出了异常;
(2)throws
作用在方法的声明上,表示抛出异常,由调用者来进行异常处理;
可能出现异常,不一定会发生异常;
75. final、finally、finalize 有什么区别?
final:是修饰符,如果修饰类,此类不能被继承;如果修饰方法和变量,则表示此方法和此变量不能在被改变,只能使用。
finally:是 try{} catch{} finally{} 最后一部分,表示不论发生任何情况都会执行,finally 部分可以省略,但如果 finally 部分存在,则一定会执行 finally 里面的代码。
finalize:是 Object 类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法。
final可以修饰类,变量,方法,修饰的类不能被继承,修饰的变量不能重新赋值,修饰的方法不能被重写
finally用于抛异常,finally代码块内语句无论是否发生异常,都会在执行finally,常用于一些流的关闭。
finalize方法用于垃圾回收。
一般情况下不需要我们实现finalize,当对象被回收的时候需要释放一些资源,比如socket链接,在对象初始化时创建,整个生命周期内有效,那么需要实现finalize方法,关闭这个链接。
但是当调用finalize方法后,并不意味着gc会立即回收该对象,所以有可能真正调用的时候,对象又不需要回收了,然后到了真正要回收的时候,因为之前调用过一次,这次又不会调用了,产生问题。所以,不推荐使用finalize方法。
76. try-catch-finally 中哪个部分可以省略?
try-catch-finally 其中 catch 和 finally 都可以被省略,但是不能同时省略,也就是说有 try 的时候,必须后面跟一个 catch 或者 finally。
77. try-catch-finally 中,如果 catch 中 return 了,finally 还会执行吗?
finally 一定会执行,即使是 catch 中 return 了,catch 中的 return 会等 finally 中的代码执行完之后,才会执行。
78. 常见的异常类有哪些?
NullPointerException 空指针异常
ClassNotFoundException 指定类不存在
NumberFormatException 字符串转换为数字异常
IndexOutOfBoundsException 数组下标越界异常
ClassCastException 数据类型转换异常
FileNotFoundException 文件未找到异常
NoSuchMethodException 方法不存在异常
IOException IO 异常
SocketException Socket 异常
NullPointerException:空指针异常;
SQLException:数据库相关的异常;
IndexOutOfBoundsException:数组下角标越界异常;
FileNotFoundException:打开文件失败时抛出;
IOException:当发生某种IO异常时抛出;
ClassCastException:当试图将对象强制转换为不是实例的子类时,抛出此异常;
NoSuchMethodException:无法找到某一方法时,抛出;
ArrayStoreException:试图将错误类型的对象存储到一个对象数组时抛出的异常;
NumberFormatException:当试图将字符串转换成数字时,失败了,抛出;
IllegalArgumentException 抛出的异常表明向方法传递了一个不合法或不正确的参数。
ArithmeticException当出现异常的运算条件时,抛出此异常。例如,一个整数“除以零”时,抛出此类的一个实例。
网络
79. http 响应码 301 和 302 代表的是什么?有什么区别?
301:永久重定向。
302:暂时重定向。
它们的区别是,301 对搜索引擎优化(SEO)更加有利;302 有被提示为网络拦截的风险。
301和302状态码都表示重定向,当浏览器拿到服务器返回的这个状态码后悔自动跳转到一个新的URL地址。
301代表永久性重定向,旧地址被永久移除,客户端向新地址发送请求。
302代表暂时性重定向,旧地址还在,客户端继续向旧地址发送请求。
303代表暂时性重定向,重定向到新地址时,必须使用GET方法请求新地址。
307代表暂时性重定向,与302的区别在于307不允许从POST改为GET。
307代表永久性重定向,与301的区别在于308不允许从POST改为GET。
80. forward 和 redirect 的区别?
forward 是转发 和 redirect 是重定向:
地址栏 url 显示:foward url 不会发生改变,redirect url 会发生改变;
数据共享:forward 可以共享 request 里的数据,redirect 不能共享;
效率:forward 比 redirect 效率高。
forward是直接请求转发;redirect是间接请求转发,又叫重定向。
forward,客户端和浏览器执行一次请求;redirect,客户端和浏览器执行两次请求。
forward,经典的MVC模式就是forward;redirect,用于避免用户的非正常访问。(例如用户非正常访问,servlet就可以将HTTP请求重定向到登录页面)。
forward,地址不变;redirect,地址改变。
forward常用方法:RequestDispatcher类的forward()方法;redirect常用方法:HttpServletRequest类的sendRedirect()方法。
81. 简述 tcp 和 udp的区别?
tcp 和 udp 是 OSI 模型中的运输层中的协议。tcp 提供可靠的通信传输,而 udp 则常被用于让广播和细节控制交给应用的通信传输。
两者的区别大致如下:
tcp 面向连接,udp 面向非连接即发送数据前不需要建立链接;
tcp 提供可靠的服务(数据传输),udp 无法保证;
tcp 面向字节流,udp 面向报文;
tcp 数据传输慢,udp 数据传输快;
- TCP是传输控制协议,UDP是用户数据表协议;
- TCP长连接,UDP无连接;
- UDP程序结构较简单,只需发送,无须接收;
- TCP可靠,保证数据正确性、顺序性;UDP不可靠,可能丢数据;
- TCP适用于少量数据,UDP适用于大量数据传输;
- TCP速度慢,UDP速度快;
82. tcp 为什么要三次握手,两次不行吗?为什么?
如果采用两次握手,那么只要服务器发出确认数据包就会建立连接,但由于客户端此时并未响应服务器端的请求,那此时服务器端就会一直在等待客户端,这样服务器端就白白浪费了一定的资源。若采用三次握手,服务器端没有收到来自客户端的再此确认,则就会知道客户端并没有要求建立请求,就不会浪费服务器的资源。
因为客户端和服务端都要确认连接,①客户端请求连接服务端;②针对客户端的请求确认应答,并请求建立连接;③针对服务端的请求确认应答,建立连接;
两次无法确保A能收到B的数据;
83. 说一下 tcp 粘包是怎么产生的?
tcp 粘包可能发生在发送端或者接收端,分别来看两端各种产生粘包的原因:
发送端粘包:发送端需要等缓冲区满才发送出去,造成粘包;
接收方粘包:接收方不及时接收缓冲区的包,造成多个包接收。
发送方需要等缓冲区满才能发送出去,造成粘包;
接收方不及时接收缓冲区的包,造成粘包;
84. OSI 的七层模型都有哪些?
物理层:利用传输介质为数据链路层提供物理连接,实现比特流的透明传输。
数据链路层:负责建立和管理节点间的链路。
网络层:通过路由选择算法,为报文或分组通过通信子网选择最适当的路径。
传输层:向用户提供可靠的端到端的差错和流量控制,保证报文的正确传输。
会话层:向两个实体的表示层提供建立和使用连接的方法。
表示层:处理用户信息的表示问题,如编码、数据格式转换和加密解密等。
应用层:直接向用户提供服务,完成用户希望在网络上完成的各种工作。
85. get 和 post 请求有哪些区别?
get 请求会被浏览器主动缓存,而 post 不会。
get 传递参数有大小限制,而 post 没有。
post 参数传输更安全,get 的参数会明文限制在 url 上,post 不会。
get请求参数是连接在url后面的,而post请求参数是存放在requestbody内的;
get请求因为浏览器对url长度有限制,所以参数个数有限制,而post请求参数个数没有限制;
因为get请求参数暴露在url上,所以安全方面post比get更加安全;
get请求只能进行url编码,而post请求可以支持多种编码方式;
get请求参数会保存在浏览器历史记录内,post请求并不会;
get请求浏览器会主动cache,post并不会,除非主动设置;
get请求产生1个tcp数据包,post请求产生2个tcp数据包;
在浏览器进行回退操作时,get请求是无害的,而post请求则会重新请求一次;
浏览器在发送get请求时会将header和data一起发送给服务器,服务器返回200状态码,而在发送post请求时,会先将header发送给服务器,服务器返回100,之后再将data发送给服务器,服务器返回200 OK;
102、什么是 XSS 攻击,如何避免?
xss(Cross Site Scripting),即跨站脚本攻击,是一种常见于web应用程序中的计算机安全漏洞。指的是在用户浏览器上,在渲染DOM树的时候,执行了不可预期的JS脚本,从而发生了安全问题。
XSS就是通过在用户端注入恶意的可运行脚本,若服务端对用户的输入不进行处理,直接将用户的输入输出到浏览器,然后浏览器将会执行用户注入的脚本。 所以XSS攻击的核心就是浏览器渲染DOM的时候将文本信息解析成JS脚本从而引发JS脚本注入,那么XSS攻击的防御手段就是基于浏览器渲染这一步去做防御。只要我们使用HTML编码将浏览器需要渲染的信息编码后,浏览器在渲染DOM元素的时候,会自动解码需要渲染的信息,将上述信息解析成字符串而不是JS脚本,这就是我们防御XSS攻击的核心想法。
预防:
1、获取用户的输入,不用innerHtml,用innerText.
2、对用户的输入进行过滤,如对& < > " ' /等进行转义;
103、什么是 CSRF 攻击,如何避免?
跨站请求伪造(英语:Cross-site request forgery),也被称为 one-click attack 或者 session riding,通常缩写为 CSRF 或者 XSRF, 是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。跟跨网站脚本(XSS)相比,XSS 利用的是用户对指定网站的信任,CSRF 利用的是网站对用户网页浏览器的信任。
1、攻击细节
跨站请求攻击,简单地说,是攻击者通过一些技术手段欺骗用户的浏览器去访问一个自己曾经认证过的网站并运行一些操作(如发邮件,发消息,甚至财产操作如转账和购买商品)。由于浏览器曾经认证过,所以被访问的网站会认为是真正的用户操作而去运行。这利用了web中用户身份验证的一个漏洞:简单的身份验证只能保证请求发自某个用户的浏览器,却不能保证请求本身是用户自愿发出的。
例子
假如一家银行用以运行转账操作的URL地址如下:http://www.examplebank.com/withdraw?account=AccoutName&amount=1000&for=PayeeName
那么,一个恶意攻击者可以在另一个网站上放置如下代码: <img src="http://www.examplebank.com/withdraw?account=Alice&amount=1000&for=Badman">
如果有账户名为Alice的用户访问了恶意站点,而她之前刚访问过银行不久,登录信息尚未过期,那么她就会损失1000资金。
这种恶意的网址可以有很多种形式,藏身于网页中的许多地方。此外,攻击者也不需要控制放置恶意网址的网站。例如他可以将这种地址藏在论坛,博客等任何用户生成信息的网站中。这意味着如果服务端没有合适的防御措施的话,用户即使访问熟悉的可信网站也有受攻击的危险。
透过例子能够看出,攻击者并不能通过CSRF攻击来直接获取用户的账户控制权,也不能直接窃取用户的任何信息。他们能做到的,是欺骗用户浏览器,让其以用户的名义运行操作。
2、防御措施
检查Referer字段
HTTP头中有一个Referer字段,这个字段用以标明请求来源于哪个地址。在处理敏感数据请求时,通常来说,Referer字段应和请求的地址位于同一域名下。以上文银行操作为例,Referer字段地址通常应该是转账按钮所在的网页地址,应该也位于www.examplebank.com之下。而如果是CSRF攻击传来的请求,Referer字段会是包含恶意网址的地址,不会位于www.examplebank.com之下,这时候服务器就能识别出恶意的访问。
这种办法简单易行,工作量低,仅需要在关键访问处增加一步校验。但这种办法也有其局限性,因其完全依赖浏览器发送正确的Referer字段。虽然http协议对此字段的内容有明确的规定,但并无法保证来访的浏览器的具体实现,亦无法保证浏览器没有安全漏洞影响到此字段。并且也存在攻击者攻击某些浏览器,篡改其Referer字段的可能。
3、添加校验token
由于CSRF的本质在于攻击者欺骗用户去访问自己设置的地址,所以如果要求在访问敏感数据请求时,要求用户浏览器提供不保存在cookie中,并且攻击者无法伪造的数据作为校验,那么攻击者就无法再运行CSRF攻击。这种数据通常是窗体中的一个数据项。服务器将其生成并附加在窗体中,其内容是一个伪随机数。当客户端通过窗体提交请求时,这个伪随机数也一并提交上去以供校验。正常的访问时,客户端浏览器能够正确得到并传回这个伪随机数,而通过CSRF传来的欺骗性攻击中,攻击者无从事先得知这个伪随机数的值,服务端就会因为校验token的值为空或者错误,拒绝这个可疑请求。
86. 如何实现跨域?
实现跨域有以下几种方案:
服务器端运行跨域 设置 CORS 等于 *;
在单个接口使用注解 @CrossOrigin 运行跨域;
使用 jsonp 跨域;
87. 说一下 JSONP 实现原理?
jsonp:JSON with Padding,它是利用script标签的 src 连接可以访问不同源的特性,加载远程返回的“JS 函数”来执行的。
设计模式
jsonp原理详解——终于搞清楚jsonp是啥了_哪 吒的博客-优快云博客
2、最流行的跨域方案cors
cors是目前主流的跨域解决方案,跨域资源共享(CORS) 是一种机制,它使用额外的 HTTP 头来告诉浏览器 让运行在一个 origin (domain) 上的Web应用被准许访问来自不同源服务器上的指定的资源。当一个资源从与该资源本身所在的服务器不同的域、协议或端口请求一个资源时,资源会发起一个跨域 HTTP 请求。
3、最方便的跨域方案Nginx
nginx是一款极其强大的web服务器,其优点就是轻量级、启动快、高并发。
现在的新项目中nginx几乎是首选,我们用node或者java开发的服务通常都需要经过nginx的反向代理。
反向代理的原理很简单,即所有客户端的请求都必须先经过nginx的处理,nginx作为代理服务器再讲请求转发给node或者java服务,这样就规避了同源策略。
105、websocket应用的是哪个协议
WebSocket是一个允许Web应用程序(通常指浏览器)与服务器进行双向通信的协议。HTML5的WebSocket API主要是为浏览器端提供了一个基于TCP协议实现全双工通信的方法。
WebSocket优势: 浏览器和服务器只需要要做一个握手的动作,在建立连接之后,双方可以在任意时刻,相互推送信息。同时,服务器与客户端之间交换的头信息很小。
设计模式
88. 说一下你熟悉的设计模式?
单例模式:保证被创建一次,节省系统开销。
工厂模式(简单工厂、抽象工厂):解耦代码。
观察者模式:定义了对象之间的一对多的依赖,这样一来,当一个对象改变时,它的所有的依赖者都会收到通知并自动更新。
外观模式:提供一个统一的接口,用来访问子系统中的一群接口,外观定义了一个高层的接口,让子系统更容易使用。
模版方法模式:定义了一个算法的骨架,而将一些步骤延迟到子类中,模版方法使得子类可以在不改变算法结构的情况下,重新定义算法的步骤。
状态模式:允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。
1、单例模式
作用:保证类只有一个实例。
JDK中体现:Runtime类。
2、静态工厂模式
作用:代替构造函数创建对象,方法名比构造函数清晰。
JDK中体现:Integer.valueOf、Class.forName
3、抽象工厂
作用:创建某一种类的对象。
JDK中体现:Java.sql包。
4、原型模式
clone();
原型模式的本质是拷贝原型来创建新的对象,拷贝是比new更快的创建对象的方法,当需要大批量创建新对象而且都是同一个类的对象的时候考虑使用原型模式。
一般的克隆只是浅拷贝(对象的hash值不一样,但是对象里面的成员变量的hash值是一样的)。
有些场景需要深拷贝,这时我们就要重写clone方法,以ArrayList为例:
5、适配器模式
作用:使不兼容的接口相容。
JDK中体现:InputStream、OutputStream。
6、装饰器模式
作用:为类添加新的功能,防止类继承带来的类爆炸。
JDK中体现:io类、Collections、List。
7、外观模式
作用:封装一组交互类,一直对外提供接口。
JDK中体现:logging包。
8、享元模式
作用:共享对象、节省内存。
JDK中体现:Integer.valueOf、String常量池。
9、代理模式
作用:
(1)透明调用被代理对象,无须知道复杂实现细节;
(2)增加被代理类的功能;
JDK中体现:动态代理。
10、迭代器模式
作用:将集合的迭代和集合本身分离。
JDK中体现:Iterator
11、命令模式
作用:封装操作,使接口一致。
JDK中体现:Runable、Callable、ThreadPoolExecutor。
08、什么是设计模式?你是否在你的代码里面使用过任何设计模式?
1、什么是设计模式?
设计模式是解决软件开发某些特定问题而提出的一些解决方案,也可以理解为解决问题的一些固定思路。
通过设计模式可以帮助我们增强代码的可复用性、可扩展性、灵活性。
我们使用设计模式的最终目的是实现代码的高内聚、低耦合。
2、设计模式的七大原则
单一职责原则
接口隔离原则
依赖倒转原则
里式替换原则
开闭原则
迪米特法则
合成复用原则
3、你是否在你的代码里面使用过任何设计模式?
(1)单例模式
JDK种的runtime,Spring种的singeton。
(2)简单工厂模式
Spring的BeanFactory,根据传入一个唯一标识来获得bean对象。
(3)原型模式
clone()
(4)代理模式
Spring的AOP中,Spring实现AOP功能的原理就是代理模式,①JDK动态代理。②CGLIB动态代理,使用Advice(通知)对类进行方法级别的切面增强。
(5)装饰器模式
为类添加新的功能,防止类爆炸;
IO流、数据源包装,Spring中用到的装饰器模式表现在Wrapper。
109、Java 中什么叫单例设计模式?请用 Java 写出线程安全的单例模式
保证程序只有一个对象的实例,叫做单例模式;
内部类的方式实现单例模式,是线程安全的;
双重验证方式实现单例模式也是线程安全的;
110、在 Java 中,什么叫观察者设计模式(observer design pattern)?
1、观察者模式是一种一对多的依赖关系,让多个观察者同时监听某一主题对象。当这个主题对象发生变化时,会通知所有观察者对象,使它们能够自动更新自己。
2、JAVA提供的对观察者模式的支持
在JAVA语言的java.util库里面,提供了一个Observable类以及一个Observer接口,构成JAVA语言对观察者模式的支持。
(1)Observer接口
这个接口只定义了一个方法,即update()方法,当被观察者对象的状态发生变化时,被观察者对象的notifyObservers()方法就会调用这一方法。
public interface Observer {
void update(Observable o, Object arg);
}
(2)Observable类
被观察者类都是java.util.Observable类的子类。java.util.Observable提供公开的方法支持观察者对象,这些方法中有两个对Observable的子类非常重要:一个是setChanged(),另一个是notifyObservers()。第一方法setChanged()被调用之后会设置一个内部标记变量,代表被观察者对象的状态发生了变化。第二个是notifyObservers(),这个方法被调用时,会调用所有登记过的观察者对象的update()方法,使这些观察者对象可以更新自己。
111、使用工厂模式最主要的好处是什么?在哪里使用?
1、工厂模式好处
良好的封装性、代码结构清晰;
扩展性好,如果想增加一个产品,只需扩展一个工厂类即可;
典型的解耦框架;
2、在哪里使用?
需要生成对象的地方;
不同数据库的访问;
112、请解释自动装配模式的区别?
有五种自动装配的方式,可以用来指导 Spring 容器用自动装配方式来进行依赖注入。
1、no
默认的方式是不进行自动装配,通过显式设置 ref 属性来进行装配。第 402 页 共 485 页
2、byName
通过参数名 自动装配,Spring 容器在配置文件中发现 bean
的 autowire 属性被设置成 byname,之后容器试图匹配、装配和该 bean 的属
性具有相同名字的 bean。
3、byType:
通过参数类型自动装配,Spring 容器在配置文件中发现 bean
的 autowire 属性被设置成 byType,之后容器试图匹配、装配和该 bean 的属
性具有相同类型的 bean。如果有多个 bean 符合条件,则抛出错误。
4、constructor
这个方式类似于 byType, 但是要提供给构造器参数,如
果没有确定的带参数的构造器参数类型,将会抛出异常。
5、autodetect
首先尝试使用 constructor 来自动装配,如果无法工作,
则使用 byType 方式。
113、举一个用 Java 实现的装饰模式(decorator design pattern)?它是作用于对象层次还是类层次?
在Java IO中运用了装饰器模式,inputStream作为抽象类,其下有几个实现类,表示从不同的数据源输入:
byteArrayInputStream
fileInputStream
StringBufferInputStream
PipedInputStream,从管道产生输入;
SequenceInputStream,可将其他流收集合并到一个流内;
FilterInputStream作为装饰器在JDK中是一个普通类,其下面有多个具体装饰器比如BufferedInputStream、DataInputStream等。
FilterInputStream内部封装了基础构件:
protected volatile InputStream in;
而BufferedInputStream在调用其read()读取数据时会委托基础构件来进行更底层的操作,而它自己所起的装饰作用就是缓冲,在源码中可以很清楚的看到这一切。
89. 简单工厂和抽象工厂有什么区别?
简单工厂:用来生产同一等级结构中的任意产品,对于增加新的产品,无能为力。
工厂方法:用来生产同一等级结构中的固定产品,支持增加任意产品。
抽象工厂:用来生产不同产品族的全部产品,对于增加新的产品,无能为力;支持增加产品族。