Interview Questions and Answers
开发人员面试题集锦
Common
谈谈对mvc的认识
- 由模型(model),视图(view),控制器(controller)完成的应用程序。
- model层负责提供数据,和数据库有关的操作都交给模型层来处理,view层则提供交互的界面,并输出数据,而controller层则负责接收请求,并分发给相应的model来处理,然后调用view层来显示。
表单提交中的Get和Post的异同点
- GET在浏览器回退时是无害的,而POST会再次提交请求。
- GET产生的URL地址可以被Bookmark,而POST不可以。
- GET请求会被浏览器主动cache,而POST不会,除非手动设置。
- GET请求只能进行url编码,而POST支持多种编码方式。
- GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。
- GET请求在URL中传送的参数是有长度限制的,而POST没有。
- 对参数的数据类型,GET只接受ASCII字符,而POST没有限制。
- GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。
- GET参数通过URL传递,POST放在Request body中。
- GET产生一个TCP数据包,POST产生两个TCP数据包
session 与 cookie 的区别和联系
区别:
- 存放位置:Session 保存在服务器,Cookie 保存在客户端。
- 存放的形式:Session 是以对象的形式保存在服务器,Cookie 以字符串的形式保存在客户端。
- 用途:Cookies 适合做保存用户的个人设置,爱好等,Session 适合做客户的身份验证
- 路径:Session 不能区分路径,同一个用户在访问一个网站期间,所有的 Session 在任何一个地方都可以访问到。而 Cookie 中如果设置了路径参数,那么同一个网站中不同路径下的 Cookie 互相是访问不到的。
- 安全性:Cookie 不是很安全,别人可以分析存放在本地的 COOKIE 并进行 COOKIE 欺骗,考虑到安全应当使用 session
- 大小以及数量限制:每个域名所包含的 cookie 数:IE7/8,FireFox:50 个,Opera30 个; Cookie 总大小:Firefox 和 Safari 允许 cookie 多达 4097 个字节,Opera 允许 cookie 多达 4096 个字 节,InternetExplorer 允许 cookie 多达 4095 个字节;一般认为 Session 没有大小和数量限制。
关系:
- Session 需要借助 Cookie 才能正常工作。如果客户端完全禁止 Cookie,Session 将失效!因为 Session 是由应用服务器维持的一个 服务器端的存储空间,用户在连接服务器时,会由服务器生成一个唯一的 SessionID, 用该 SessionID 为标识符来存取服务器端的 Session 存储空间。而 SessionID 这一数据则是保存到客户端,用 Cookie 保存的,用户提交页面时,会将这一 SessionID 提交到服务器端,来存取 Session 数据。这一过程,是不用开发人员干预的。所以一旦客户端禁用 Cookie,那么 Session 也会失效。
线程和进程的区别?
- 简而言之,进程是程序运行和资源分配的基本单位,一个程序至少有一个进程,一个进程至少有一个线程。进程在执行过程中拥有独立的内存单元,而多个线程共享内存资源,减少切换次数,从而效率更高。线程是进程的一个实体,是cpu调度和分派的基本单位,是比程序更小的能独立运行的基本单位。同一进程中的多个线程之间可以并发执行。
线程有哪些状态?
线程通常都有五种状态,创建、就绪、运行、阻塞和死亡。
- 创建状态。在生成线程对象,并没有调用该对象的start方法,这是线程处于创建状态。
- 就绪状态。当调用了线程对象的start方法之后,该线程就进入了就绪状态,但是此时线程调度程序还没有把该线程设置为当前线程,此时处于就绪状态。在线程运行之后,从等待或者睡眠中回来之后,也会处于就绪状态。
- 运行状态。线程调度程序将处于就绪状态的线程设置为当前线程,此时线程就进入了运行状态,开始运行run函数当中的代码。
- 阻塞状态。线程正在运行的时候,被暂停,通常是为了等待某个时间的发生(比如说某项资源就绪)之后再继续运行。sleep,suspend,wait等方法都可以导致线程阻塞。
- 死亡状态。如果一个线程的run方法执行结束或者调用stop方法后,该线程就会死亡。对于已经死亡的线程,无法再使用start方法令其进入就绪
什么是死锁?
- 死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。是操作系统层面的一个错误,是进程死锁的简称,最早在 1965 年由 Dijkstra 在研究银行家算法时提出的,它是计算机操作系统乃至整个并发程序设计领域最难处理的问题之一。
怎么防止死锁?
- 死锁的四个必要条件:
- 互斥条件:进程对所分配到的资源不允许其他进程进行访问,若其他进程访问该资源,只能等待,直至占有该资源的进程使用完成后释放该资源
- 请求和保持条件:进程获得一定的资源之后,又对其他资源发出请求,但是该资源可能被其他进程占有,此事请求阻塞,但又对自己获得的资源保持不放
- 不可剥夺条件:是指进程已获得的资源,在未完成使用之前,不可被剥夺,只能在使用完后自己释放
- 环路等待条件:是指进程发生死锁后,若干进程之间形成一种头尾相接的循环等待资源关系
- 这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之 一不满足,就不会发生死锁。
- 理解了死锁的原因,尤其是产生死锁的四个必要条件,就可以最大可能地避免、预防和 解除死锁。
- 所以,在系统设计、进程调度等方面注意如何不让这四个必要条件成立,如何确 定资源的合理分配算法,避免进程永久占据系统资源。
- 此外,也要防止进程在处于等待状态的情况下占用资源。因此,对资源的分配要给予合理的规划。
ORM 代表什么?
- ORM 代表对象关系映射,把数据库相关字段映射到对应的模型对象里面,相当于有多个一个抽象层。后面直接操作对象
什么是 Redis 穿透和雪崩
缓存穿透
- 当访问redis中一个不存在的key的时候,会直接穿过缓存,去数据库中进行查询.
- 如果是黑客,进行恶意攻击的时候,每次都请求超过2000个/秒的时候,这个时候mysql基本上就挂了.
- 解决办法是:每次从数据库中查询到一个不存在的key的时候,就写一个空值到缓存库中,有恶意攻击的时候,直接从缓存中取到这个空值.
缓存雪崩
- 假设每秒有5000个请求过来时候,redis缓存库崩了,然后这些请求瞬间落在了mysql数据库上,直接导致数据库死机. 解决方案就是:
- 事前:提高缓存库的高可用, 使用主从结构加哨兵 cluster集群
- 事中:使用ehcache+hystrix限流组件(当请求量非常巨大的时候,就调用自己开发好的一个降级饿组件,返回一些默认值,如友情提示,或者空白值)
- 事后:做持久化,尽快恢复缓存集群,一旦恢复,自动从磁盘上读取数据,恢复内存中的数据。
MySQL
对关系型数据库而言,索引是相当重要的概念,请回答有关索引几个问题:
a) 索引的目的是什么?
- 快速访问数据表中的特定信息,提高检索速度
- 创建唯一性索引,保证数据库表中每一行数据的唯一性
- 加速表和表之间的连接
- 使用分组和排序子句进行数据检索时,可以显著减少查询中分组和排序的时间
b) 索引对数据库系统的负面影响是什么?
- 负面影响:创建索引和维护索引需要耗费时间,这个时间随着数据量的增加而增加;索引需要占用物理空间,不光是表需要占用数据空间,每个索引也需要占用物理空间;当对表进行增、删、改的时候索引也要动态维护,这样就降低了数据的维护速度。
c) 为数据表建立索引的原则有哪些?
- 在最频繁使用的、用以缩小查询范围的字段上建立索引
- 在平频繁使用的、需要排序的字段上建立索引
d) 什么情况下不宜建立索引?
- 对于查询中很少涉及的列或者重复值比较多的列,不宜建立索引
- 对于一些特殊的数据类型,不宜建立索引,比如文本字段(text),值范围较少的知道等。
优化mysql 数据库方法
- 选取适当的字段,打字段设置为NOT NULL,在查询的时候数据库不用比较NULL;
- 使用链接(join)代替子查询;
- 使用联合(UNION)查询代替手动创建临时表;
- 尽量减少使用(LIKE)关键字和通配符
- 使用事务和外健
- Where子句中:where表之间的连接必须写在其他Where条件之前,那些可以过滤掉最大数量记录的条件必须写在Where子句的末尾.HAVING最后。
- 用EXISTS替代IN、用NOT EXISTS替代NOT IN。
- 避免在索引列上使用计算
- 避免在索引列上使用IS NULL和IS NOT NULL
- 对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。
- 应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描
- 应尽量避免在 where 子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描
PHP
require,include 区别
- require是无条件包含也就是如果一个流程里加入require,无论条件成立与否都会先执行require include有返回值,而require没有(可能因为如此require的速度比include快) 包含文件不存在或者语法错误的时候require是致命的错误终止执行,include不是
PHP字符串中单引号与双引号的区别?
- 单引号不能解释变量,而双引号可以解释变量。
- 单引号不能转义字符,在双引号中可以转义字符。
常用字符串函数。
- serialize()、unserialize() 序列化是将变量转换为可保存或传输的字符串的过程。
- strlen() 返回字符串长度。
- strrev() 反转字符串。
- strpos(原字符串,待查找字符串) 存在返回第一个字符下标,不存在返回false。
- strstr(原字符串,待查找字符串) 返回待查找字符串及其后剩余部分,不存在返回false。
- str_replace("world", "Kitty", "Hello world!") 将某个字符串替换为另一个字符串。
- explode(" ",原字符串) 将原字符串按分割字符串转成数组。
- implode(" ",原数组) 将原数组中的元素连接分割字符组合成字符串。
- trim() 移除字符串两侧的空白字符和其他字符。ltrim()移除左边、rtrim()移除右边。
- substr("Hello world",6) 返回字符串的一部分。
- substr_replace(string,replacement,start,length) 函数把字符串的一部分替换为另一个字符串。
- htmlspecialchars() 把一些预定义的字符转换为 HTML 实体。
- str_repeat("Shanghai",5) 字符串重复指定次数。
- str_split("Shanghai",3) 将字符串分割成数组,可以指定每个数组元素长度。
mysqlfetchrow() 和mysqlfetcharray之间有什么区别?
- 这两个函数,返回的都是一个数组,区别就是第一个函数返回的数组是只包含值,我们只能$row[0],$row[1],这样以数组下标来读取数据,
- 而mysqlfetcharray()返回的数组既包含第一种,也包含键值对的形式,我们可以这样读取数据,(假如数据库的字段是 username,passwd):$row['username']$row['passwd']
Laravel
什么是 HTTP 中间件?
- HTTP 中间件是一种用于过滤 HTTP 请求的技术。Laravel 包含一个中间件,用于检查应用程序用户是否已通过身份验证。
什么是数据迁移为什么迁移很重要?
- 迁移非常重要是因为它允许您通过维护数据库一致性来共享应用程序。
- 如果不进行迁移,则很难共享任何 Laravel 应用程序。
- 它还允许您同步数据库。
如何在 Laravel 模型中自定义表名?
- 自定义表名,您可以重写 protected 变量 $table 的值。
Java
普通类和抽象类有哪些区别?
- 普通类不能包含抽象方法,抽象类可以包含抽象方法。
- 抽象类不能直接实例化,普通类可以直接实例化。
Array 和 ArrayList 有何区别?
- Array可以容纳基本类型和对象,而ArrayList只能容纳对象。
- Array是指定大小的,而ArrayList大小是固定的。
- Array没有提供ArrayList那么多功能,比如addAll、removeAll和iterator等。
jsp 有哪些内置对象?作用分别是什么?
- JSP有9个内置对象:
- request:封装客户端的请求,其中包含来自GET或POST请求的参数;
- response:封装服务器对客户端的响应;
- pageContext:通过该对象可以获取其他对象;
- session:封装用户会话的对象;
- application:封装服务器运行环境的对象;
- out:输出服务器响应的输出流对象;
- config:Web应用的配置对象;
- page:JSP页面本身(相当于Java程序中的this);
- exception:封装页面抛出异常的对象。
什么是 java 序列化?什么情况下需要序列化?
- 简单说就是为了保存在内存中的各种对象的状态(也就是实例变量,不是方法),并且可以把保存的对象状态再读出来。虽然你可以用你自己的各种各样的方法来保存object states,但是Java给你提供一种应该比你自己好的保存对象状态的机制,那就是序列化。
- 什么情况下需要序列化:
- a)当你想把的内存中的对象状态保存到一个文件中或者数据库中时候;
- b)当你想用套接字在网络上传送对象的时候;
- c)当你想通过RMI传输对象的时候;
什么是反射?
- 反射主要是指程序可以访问、检测和修改它本身状态或行为的一种能力
- Java反射:
- 在Java运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意一个对象,能否调用它的任意一个方法
- Java反射机制主要提供了以下功能:
- 在运行时判断任意一个对象所属的类。
- 在运行时构造任意一个类的对象。
- 在运行时判断任意一个类所具有的成员变量和方法。
- 在运行时调用任意一个对象的方法。
接口和抽象类有什么区别?
- 实现:抽象类的子类使用 extends 来继承;接口必须使用 implements 来实现接口。
- 构造函数:抽象类可以有构造函数;接口不能有。
- main 方法:抽象类可以有 main 方法,并且我们能运行它;接口不能有 main 方法。
- 实现数量:类可以实现很多个接口;但是只能继承一个抽象类。
- 访问修饰符:接口中的方法默认使用 public 修饰;抽象类中的方法可以是任意访问修饰符。
String 属于基础的数据类型吗?
- String 不属于基础类型,基础类型有 8 种:byte、boolean、char、short、int、float、long、double,而 String 属于对象。
java 中操作字符串都有哪些类?它们之间有什么区别?
- 操作字符串的类有:String、StringBuffer、StringBuilder。
- String 和 StringBuffer、StringBuilder 的区别在于 String 声明的是不可变的对象,每次操作都会生成新的 String 对象,然后将指针指向新的 String 对象,而 StringBuffer、StringBuilder 可以在原有对象的基础上进行操作,所以在经常改变字符串内容的情况下最好不要使用 String。
- StringBuffer 和 StringBuilder 最大的区别在于,StringBuffer 是线程安全的,而 StringBuilder 是非线程安全的,但 StringBuilder 的性能却高于 StringBuffer,所以在单线程环境下推荐使用 StringBuilder,多线程环境下推荐使用 StringBuffer。
HashMap 的实现原理?
- HashMap概述:HashMap是基于哈希表的Map接口的非同步实现。此实现提供所有可选的映射操作,并允许使用null值和null键。此类不保证映射的顺序,特别是它不保证该顺序恒久不变。
- HashMap的数据结构:在java编程语言中,最基本的结构就是两种,一个是数组,另外一个是模拟指针(引用),所有的数据结构都可以用这两个基本结构来构造的,HashMap也不例外。HashMap实际上是一个“链表散列”的数据结构,即数组和链表的结合体。
- 当我们往Hashmap中put元素时,首先根据key的hashcode重新计算hash值,根绝hash值得到这个元素在数组中的位置(下标),如果该数组在该位置上已经存放了其他元素,那么在这个位置上的元素将以链表的形式存放,新加入的放在链头,最先加入的放入链尾.如果数组中该位置没有元素,就直接将该元素放到数组的该位置上。
- 需要注意Jdk 1.8中对HashMap的实现做了优化,当链表中的节点数据超过八个之后,该链表会转为红黑树来提高查询效率,从原来的O(n)到O(logn)
Spring
Spring由哪些模块组成?
以下是Spring 框架的基本模块:
- Core module
- Bean module
- Context module
- Expression Language module
- JDBC module
- ORM module
- OXM module
- Java Messaging Service(JMS) module
- Transaction module
- Web module
- Web-Servlet module
- Web-Struts module
- Web-Portlet module
什么是Spring IOC 容器?
- Spring IOC 负责创建对象,管理对象(通过依赖注入(DI),装配对象,配置对象,并且管理这些对象的整个生命周期。
- IOC 或 依赖注入把应用的代码量降到最低。它使应用容易测试,单元测试不再需要单例和JNDI查找机制。最小的代价和最小的侵入性使松散耦合得以实现。IOC容器支持加载服务时的饿汉式初始化和懒加载。
什么是Spring的依赖注入?
- 依赖注入,是IOC的一个方面,是个通常的概念,它有多种解释。这概念是说你不用创建对象,而只需要描述它如何被创建。你不在代码里直接组装你的组件和服务,但是要在配置文件里描述哪些组件需要哪些服务,之后一个容器(IOC容器)负责把他们组装起来。
有哪些不同类型的IOC(依赖注入)方式?
- 构造器依赖注入:构造器依赖注入通过容器触发一个类的构造器来实现的,该类有一系列参数,每个参数代表一个对其他类的依赖。
- Setter方法注入:Setter方法注入是容器通过调用无参构造器或无参static工厂 方法实例化bean之后,调用该bean的setter方法,即实现了基于setter的依赖注入。
哪种依赖注入方式你建议使用,构造器注入,还是 Setter方法注入?
- 你两种依赖方式都可以使用,构造器注入和Setter方法注入。最好的解决方案是用构造器参数实现强制依赖,setter方法实现可选依赖。
解释Spring框架中bean的生命周期。
- Spring容器 从XML 文件中读取bean的定义,并实例化bean。
- Spring根据bean的定义填充所有的属性。
- 如果bean实现了BeanNameAware 接口,Spring 传递bean 的ID 到 setBeanName方法。
- 如果Bean 实现了 BeanFactoryAware 接口, Spring传递beanfactory 给setBeanFactory 方法。
- 如果有任何与bean相关联的BeanPostProcessors,Spring会在postProcesserBeforeInitialization()方法内调用它们。
- 如果bean实现IntializingBean了,调用它的afterPropertySet方法,如果bean声明了初始化方法,调用此初始化方法。
- 如果有BeanPostProcessors 和bean 关联,这些bean的postProcessAfterInitialization() 方法将被调用。
- 如果bean实现了 DisposableBean,它将调用destroy()方法。
Spring框架的事务管理有哪些优点?
- 它为不同的事务API 如 JTA,JDBC,Hibernate,JPA 和JDO,提供一个不变的编程模式。
- 它为编程式事务管理提供了一套简单的API而不是一些复杂的事务API如
- 它支持声明式事务管理。
- 它和Spring各种数据访问抽象层很好得集成。