- 面试题
- 1、面向对象的三大特性和七大原则
- 2、HTTP结构组成
- 3、Mybatis mapper底层原理
- 4、SpringMVC和SpringBoot开发有什么不同
- 5、线程状态及转换,创建多线程的方式
- 6、SpringBoot常用注解
- 7、SpringBoot 怎么写Http请求
- 8、Maven拉取Jar包的过程
- 9、SpringMVC底层实现原理和组成
- 算法
- 二分查找
这个栏目算是给自己挖了个坑,给自己设定目标,希望可以坚持
目前二本大四,将近毕业,没有实习经验,秋招也没有offer;
希望可以鞭策自己,让自己更加努力;
这是这个栏目的第一篇,题目来源于11月10号的面试
面试公司:广州至真科技
面试体验:公司整体给人体验良好,公司环境也不错,技术面和HR都很友善,问的问题结合个人简历和公司技术栈,咨询问题也耐心讲解;当时面完技术一面感觉良好,以为技术二面和HR面要另外安排,没想到坐了几分钟技术二面和HR面同时进行,当时有点紧张,技术二面没答好,不过主要原因还是自身技术不过硬,希望公司可以给个机会还有就是自己加油吧 面试题 1、面向对象的三大特性和七大原则
三大特性:封装、继承、多态 具体:封装、继承、多态
七大原则:
七大原则之间并不是相互孤立的,彼此间存在着一定关联,一个可以是另一个原则的加强或是基础。违反其中的某一个,可能同时违反了其余的原则。
开闭原则是面向对象的可复用设计的基石。其他设计原则是实现开闭原则的手段和工具。
一般地,可以把这七个原则分成了以下两个部分:
设计目标:开闭原则、里氏代换原则、迪米特原则
设计方法:单一职责原则、接口分隔原则、依赖倒置原则、组合/聚合复用原则
- 单一职责原则(Single Responsibility Principle)
每一个类应该专注于做一件事情。 - 里氏替换原则(Liskov Substitution Principle)
父类可以出现的地方,子类也可出现 - 依赖倒置原则(Dependence Inversion Principle)
实现尽量依赖抽象,不依赖具体实现。本质是通过抽象(抽象类和接口)使各个类或模块的实现彼此独立,不相互影响,实现模块间的松耦合 面向要求进行依赖
核心是面向接口编程,如果没有实现依赖倒置原则,那么意味着开闭原则也无法实现 - 接口隔离原则(Interface Segregation Principle)
建立单一接口,不要建立庞大臃肿的接口,尽量细化接口,接口中的方法尽量少(避免接口污染) - 迪米特法则/最少知道原则(Law Of Demeter)
又叫最少知识原则,一个软件实体应当尽可能少的与其他实体发生相互作用。就像你要去某城市租房,没必要认识城市里全部的房东,只需要找中介即可;过分使用迪米特法则则会产生大量中介类和传递类,导致系统复杂度变大,所以在使用时要既做到结构清晰,又要高内聚低耦合。 - 开闭原则(Open Close Principle | OCP)
在面向对象设计中,要遵循对扩展开放,对修改关闭 - 组合/聚合复用原则(Composite/Aggregate Reuse Principle CARP)
优先使用对象组合(组合和聚合),而不是类继承;指在一个新对象中通过关联关系(组合和聚合关系)使用原来已经存在的一些对象,使之成为新对象的一部分,新的对象通过向这些原来已有的对象委派相应的动作或者命令达到复用已有功能的目的。
具体:面向对象设计的七大设计原则详解
HTTP请求由请求行、请求头部、空行和请求体四个部分组成。
- 请求行:包括请求方法,访问的资源URL,使用的HTTP版本。 GET 和 POST 是最常见的HTTP方
法,除此以外还包括 DELETE、HEAD、OPTIONS、PUT、TRACE 。 - 请求头:格式为“属性名:属性值”,服务端根据请求头获取客户端的信息,主要有 cookie、host、 connection、accept-language、accept-encoding、user-agent 。
- 请求体:用户的请求数据如用户名,密码等。
示例:
POST /xxx HTTP/1.1 请求行 Accept:image/gif.image/jpeg, 请求头部 Accept-Language:zh-cn Connection:Keep-Alive Host:localhost User-Agent:Mozila/4.0(compatible;MSIE5.01;Window NT5.0) Accept-Encoding:gzip,deflate username=dabin 请求体
HTTP响应也由四个部分组成,分别是:状态行、响应头、空行和响应体。
- 状态行:协议版本,状态码及状态描述。
- 响应头:响应头字段主要有 connection、content-type、content-encoding、content-length、 set-cookie、Last-Modified,、Cache-Control、Expires 。
- 响应体:服务器返回给客户端的内容。
示例:
HTTP/1.1 200 OK Server:Apache Tomcat/9.0.12 Date:Mon,6Oct2021 13:23:42 GMT Content-Length:112 响应体3、Mybatis mapper底层原理
动态代理,具体:Mybatis中Mapper动态代理的实现原理
4、SpringMVC和SpringBoot开发有什么不同SpringMVC 是Spring的一个模块,基于MVC的一个框架,无需中间层来整合,用于替代Servlet。SpringMVC= struts2+spring.SpringMVC 相当于是Struts2加上Spring的整合
优势:
- 基于组件技术,全部的应用对象,无论是控制器和视图,还是业务对象之类的都是Java组件,并且和Spring提供的其他基础结构紧密集成。
- 不依赖于Servlet API。
- 可以任意使用各种视图技术,而不仅仅局限于JSP。
- 支持各种请求资源的映射策略。
- 易扩展
SpringBoot是一个快速开发的框架,能过快速整合第三方框架,整合的基本原理是Maven依赖关系,Maven的集成,完全采用注解化,简化XML配置,内嵌HTTP服务器(Tomcate,jetty),默认嵌入Tomcat,最终以Java应用程序进行执行。
springmvc与springboot的联系和区别:
联系:
Spring最初利用工厂模式(DI)和代理模式解耦应用组件,为了解耦开发了springmvc;而实际开发过程中,经常会使用到注解,程序的样板很多,于是开发了starter,这套就是springboot。
区别:
1.springboot是约定大于配置,可以简化spring的配置流程;springmvc是基于servlet的mvc框架,个人感觉少了model中的映射。
2.以前web应用要使用到tomat服务器启动,而springboot内置服务器容器,通过@SpringBootApplication中注解类中main函数启动即可
- 继承Thread类创建线程
- 实现Runnable接口创建线程
- 实现Callable和Future创建线程
- 通过线程池创建线程。
6、SpringBoot常用注解Thread 的源码中定义了6种状态:new(新建)、runnnable(可运⾏)、blocked(阻塞)、waiting(等待)、time waiting (定时等待)和 terminated(终⽌)。
SpringBoot注解最全详解(整合超详细版本)
7、SpringBoot 怎么写Http请求当时面试官说写一个HelloWorld为例
1.用IDEA创建好一个springboot项目 依赖导入等做好
2.在controller下编写
@Controller
public class HelloController {
@RequestMapping("/hello")
@ResposeBody
public String hello(){
return "Hello World!";
}
3.在springboot启动类启动项目 访问localhost:8080即可
8、Maven拉取Jar包的过程
1.首先通过pom.xml文件的引用,先在自己本地仓库里查找,如果自己仓库里有需要的jar,就不需要向代理商(私服)去要,也就不需要执行后面下载jar包的工作,直接给项目jar。
2.如果搭建的有第三方私服,在本地仓库找不到需要的jar包时,会优先去代理商(第三方私服)要jar包,如果代理商也没有,再找厂家(中央仓库 mvnrepository.com)去下载。
3.同理,下载时的顺序,如果搭建的有代理商(第三方私服),代理商这里有项目需要依赖的jar包,直接从代理商下载到本地仓库,不用访问中央仓库。如果代理商也没有,就需要找厂家(中央仓库 )去下载。在这过程中私服会保存一下自己没有的jar包,下次本地仓库再要jar包,私服就给它了。所以从中央仓库下载后,私服和本地仓库都保存了项目需要的jar包。
4.其实代理商(第三方私服)是可以不存在的,就是采取厂家直供的模式,没有中间商赚差价,本地仓库可以直接向中央仓库要jar包,然后保存到本地,方便项目调用。
简单来说:客户端发送请求-> 前端控制器 DispatcherServlet 接受客户端请求 -> 找到处理器映射
HandlerMapping 解析请求对应的 Handler -> HandlerAdapter 会根据 Handler 来调⽤真正的处理器来处理请求,并处理相应的业务逻辑 -> 处理器返回⼀个模型视图 ModelAndView -> 视图解析器进⾏解析 -> 返回⼀个视图
对象 -> 前端控制器 DispatcherServlet 渲染数据(Model)-> 将得到视图对象返回给⽤户。
公司面试没有算法,由于自己没有算法基础,每天一道,积少成多,终身学习。
二分查找实现二分查找
public static int commonBinarySearch(int[] arr, int key) {
int low = 0;
int high = arr.length - 1;
int middle = 0; //定义middle
if (key < arr[low] || key > arr[high] || low > high) {
return -1;
}
while (low <= high) {
middle = (low + high) / 2;
if (arr[middle] > key) {
//比关键字大则关键字在左区域
high = middle - 1;
} else if (arr[middle] < key) {
//比关键字小则关键字在右区域
low = middle + 1;
} else {
return middle,count;
}
}
return -1; //最后仍然没有找到,则返回-1
}
------------------------------------------------------------
//递归实现
public static int recursionBinarySearch(int[] arr,int key,int low,int high){
if(key < arr[low] || key > arr[high] || low > high){
return -1;
}
int middle = (low + high) / 2; //初始中间位置
if(arr[middle] > key){
//比关键字大则关键字在左区域
return recursionBinarySearch(arr, key, low, middle - 1);
}else if(arr[middle] < key){
//比关键字小则关键字在右区域
return recursionBinarySearch(arr, key, middle + 1, high);
}else {
return middle;
}
}
-------------------------------------------
测试
public static void main(String[] args) {
int[] arr = {1,2,3,4,5,6,7,8,9,10};
int key = 7;
//int position = recursionBinarySearch(arr,key,0,arr.length - 1);
int position = commonBinarySearch(arr, key);
if(position == -1){
System.out.println("查找的是"+key+",序列中没有该数!");
}else{
System.out.println("查找的是"+key+",找到位置为:"+position);
}
}



