JAVA基础
- HashMap原理?为什么使用数组+链表?可以用ArrayList或LinkedList代替数组吗?HashMap为什么要进行扩容,扩容后原来的元素怎么进行处理?JDK8为什么在链表长度大于8时改用红黑树?为什么说HashMap是线程不安全的?
HashMap使用Entry数组存储键值对,每一个键值对是一个Entry实体,Entry是一个单向链表结构,所以HashMap是使用数组加链表实现的。
根据key的hash值对数组长度取模运算得到元素在数组的下标,当出现hash值一样的情况时,就在数组对应下标位置形成一条链表。
可以使用AarrayList或LinkedList代替数组。
HashMap默认数组长度是16,当元素越来越多的时候,碰撞的几率越来越高,为了提高查询效率,对数组进行扩容。扩容后原来的元素要重新计算在数组中的新位置并放入。
因为红黑树的平均查找长度是log(n),长度为8的时候,平均查找长度为3,如果继续使用链表,平均查找长度为8/2=4,这才有转换为树的必要。
在多线程的时候,put的时候可能导致数据不一致,get操作可能因为resize而引起死循环。
- ==和equals的区别?如果两个对象相等,hashcode相同么?两个对象的hashcode相同,两个对象一定相等么,为什么?
"==" 用于基本数据类型,是直接比较存储的值是否相等;如果用于引用类型的变量,比较的是所指向变量的地址。equals不能用于基本数据类型,euqals继承自Object,如果没有进行重写,比较的是变量所指向的地址,如果进行了重写,根据重写内容进行比较。
两个对象相等,它们的hashcode一定相同。hashcode相同,两个对象不一定相等,哈希冲突。
- static变量和实例变量有什么区别?static方法可以使用this,super等关键字吗?
static变量在类被虚拟机载入的时候就会进行初始化,存在于静态方法区,生命周期随类加载而加载,随类消失而消失。
实例变量在对象创建后通过对象调用,存储于堆内存种,随着类的消失而消失。
static方法不能使用this,super关键字,因为静态创建早于对象。
- 基本数据类型?自动装箱是在干什么?String是基本数据类型么?String值在初始化还能修改么?
自动装箱是将基本数据类型和对应的包装类型做一个转化。
String不是基本数据类型,是引用类型。String是final修饰的,值在初始化后不能进行修改。
- 值传递和引用传递
值传递就是在方法调用的时候,实参是将自己的一份拷贝赋给形参,在方法内,对该参数值的修改不影响原来实参。
引用传递是在方法调用的时候,实参将自己的地址传递给形参,此时方法内对该参数值的改变,就是对该实参的实际操作。
- 异常处理的时候,finally代码块的主要用来干什么?
无论是否抛出异常,finally代码块总是会被执行,finally代码块主要用来释放资源,比如:I/O缓冲区,数据库连接。
- 将一个高精度值转向低精度会发生什么,例如int转为byte?
int是32位的,而byte是8位的,强制转化后int类型的高24位将会被丢弃。
- String、StringBuffer、StringBuilder的区别?
String是只读字符串,String引用的字符串内容是不能被改变的。
StringBuilder和StringBuffer的方法完全相同,它的效率比StringBuffer要高,但是线程不安全。
ArrayList和LinkedList的区别
遍历删除ArrayList中的元素时怎么做,使用ArrayList的remove还是Iterator的remove方法?
Iterator的remove方法,否则会抛出ConcurrentModificationException。
JSP/Servlet
- cookie和session的作用、区别?
Cookie:主要用在保存客户端,其值在客户端与服务器之间传送,不安全,存储的数据量有限。
Session:保存在服务器端,每一个session在服务器端有一个sessionID作一个标识。存储的数据量大,安全性高。占用服务端的内存资源。
- jsp有哪些内置对象?作用分别是什么?
request:用户端请求,此请求会包含来自GET/POST请求的参数;
response:网页传回用户端的回应;
pageContext:网页的属性是在这里管理;
session:与请求有关的会话期;
application:servlet正在执行的内容;
out:用来传送回应的输出;
config:servlet的构架部件;
page:JSP网页本身;
exception:针对错误网页,未捕捉的例外。
- get和post的区别?
get传输的数据量小,主要是由于受URL长度的限制;而post可以传输大量的数据;
get将表单中的数据按照var=value的形式,添加到action所指向的URL后面,并且两者用“?”连接,而各个变量之间使用“&”连接;post是将表单中的数据放在form的数据体中,按照变量和值相对应的方式,传递到action所指向的URL
- servlet中请求转发和重定向的区别?
重定向(redirect)其实是两次request,第一次,客户端request,A服务器响应,并response回来,告诉浏览器,你应该去B。这个时候IE可以看到地址变了,而且历史的回退按钮也亮了。重定向可以访问自己web应用以外的资源。在重定向的过程中,传输的信息会被丢失。
请求转发(forward)是服务器内部把对一个request/response的处理权,移交给另外一个.对于客户端而言,它只知道自己最早请求的那个A,而不知道中间的B,甚至C、D。传输的信息不会丢失。
- 如果客户端禁止cookie,session 还能用吗?有什么其它办法?
一般会把存储到客户端的cookie中,如果浏览器禁用了 cookie,浏览器请求服务器无法携带 sessionid,服务器无法识别请求中的用户身份,session失效。
通过url重写将sessionid作为参数追加到url中;可以使用header
- 如何避免sql注入?
控制wen应用数据库操作权限;
对传递的参数进行格式校验;
对特殊字符做转义处理;
使用参数化sql查询,避免sql拼接
多线程
- 多线程的创建方式?
继承Thread类、实现Runnable接口、使用Executor框架来创建线程池
- 使用多线程有什么好处?
避免阻塞(异步调用)、避免CPU空转、提升性能
- 悲观锁、乐观锁的优缺点?
悲观锁:总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次拿数据的时候都会上锁,这样别人拿数据的时候就会阻塞知道它拿到锁;比如关系型数据库的行锁、表锁、读锁、写锁;比如java里面的同步原语synchronized关键字的实现也是悲观锁;
乐观锁:每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下再次期间别人有没有更新这个数据。乐观锁适用于多读的应用类型,可以提高吞吐量。
- 线程都有哪些状态,分别在什么时候处于这些状态?
新建状态:当用new操作符创建一个线程时,线程还没有开始运行,此时处于新建状态;
就绪状态:一个新创建的线程并不自动开始运行,要执行线程,必须要调用线程的start()方法,当线程对象调用start()方法即启动了线程,start()方法创建线程运行的系统资源,并调度线程运行run()方法;
运行状态:当线程获得cpu时间后,才进入运行状态,真正开始实行run()方法;
阻塞状态:a.线程通过调用sleep方法进入睡眠状态;b.线程调用一个在I/O上被阻塞的操作,即该操作在输入输出操作完成之前不会返回到它的调用者;c.线程试图得到一个锁,而该锁正被其他线程持有;d.线程正等待某个触发条件
死亡状态:run方法自然退出而自然死亡,或者一个未捕获的异常终止了run方法而使线程猝死。
- sleep方法和wait方法有什么区别?
sleep它不会释放锁,wait会放弃对象锁
数据库
- mysql和oracle下的分页实现?
mysql:是使用关键字limit来进行分页的.LIMIT [offset,] rows:offset指定要返回的第一行的偏移量(也就是从哪个索引开始),rows第二个指定返回行的最大数目。初始行的偏移量是0(不是1)
oracle:一般是使用rownum 加select 嵌套查询
- 几种连接方式及区别?
内连接: 只连接匹配的行
左外连接: 包含左边表的全部行(不管右边的表中是否存在与它们匹配的行),以及右边表中全部匹配的行
右外连接: 包含右边表的全部行(不管左边的表中是否存在与它们匹配的行),以及左边表中全部匹配的行
全外连接: 包含左、右两个表的全部行,不管另外一边的表中是否存在与它们匹配的行。
交叉连接: 生成笛卡尔积-它不使用任何匹配或者选取条件,而是直接将一个数据源中的每个行与另一个数据源的每个行都一一匹配
- 索引的优缺点
索引最大的好处是提高查询速度,
缺点是更新数据时效率低,因为要同时更新索引
对数据进行频繁查询进建立索引,如果要频繁更改数据不建议使用索引。
- sql优化方案:
sql尽量使用索引,而且查询要走索引;
表关联时大数据量的表做主表;
SELECT子句中避免使用*号;
多使用内部函数提高SQL效率;
避免在索引列上使用计算等
- 开发中使用数据库连接池的好处?
维护一定数量的连接,减少创建连接的时间;更快的响应时间;统一的管理。
- 如果不考虑事务的隔离性,会发生什么问题?
脏读是指在一个事务处理过程里读取了另一个未提交的事务中的数据。
不可重复读是指在对于数据库中的某个数据,一个事务范围内多次查询却返回了不同的数据值,这是由于在查询间隔,被另一个事务修改并提交了。
Spring
- AOP与IOC的概念
IOC就是控制反转,是指创建对象的控制权的转移,以前创建对象的主动权和时机是由自己把控的,而现在这种权力转移到Spring容器中,并由容器根据配置文件去创建实例和管理各个实例之间的依赖关系,对象与对象之间松散耦合,也利于功能的复用。
AOP,一般称为面向切面,作为面向对象的一种补充,用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取并封装为一个可重用的模块,这个模块被命名为“切面”(Aspect),减少系统中的重复代码,降低了模块间的耦合度,同时提高了系统的可维护性。
- Spring中用到了哪些设计模式?
(1)工厂模式:BeanFactory就是简单工厂模式的体现,用来创建对象的实例;
(2)单例模式:Bean默认为单例模式。
(3)代理模式:Spring的AOP功能用到了JDK的动态代理和CGLIB代理;
(4)模板方法:用来解决代码重复的问题。比如. RestTemplate, JmsTemplate, JpaTemplate。
(5)观察者模式:定义对象键一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知被制动更新,如Spring中listener的实现--ApplicationListener。
- Spring事务的实现方式?
编程式事务管理使用TransactionTemplate。
声明式事务管理建立在AOP之上的。其本质是通过AOP功能,对方法前后进行拦截,将事务处理的功能编织到拦截的方法中,也就是在目标方法开始之前加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。
- SpringMVC的运行流程
(1)用户发送请求至前端控制器DispatcherServlet;
(2) DispatcherServlet收到请求后,调用HandlerMapping处理器映射器,请求获取Handle;
(3)处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet;
(4)DispatcherServlet 调用 HandlerAdapter处理器适配器;
(5)HandlerAdapter 经过适配调用 具体处理器(Handler,也叫后端控制器);
(6)Handler执行完成返回ModelAndView;
(7)HandlerAdapter将Handler执行结果ModelAndView返回给DispatcherServlet;
(8)DispatcherServlet将ModelAndView传给ViewResolver视图解析器进行解析;
(9)ViewResolver解析后返回具体View;
(10)DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)
(11)DispatcherServlet响应用户。
- SpringMVC常用的注解有哪些?
@RequestMapping:用于处理请求 url 映射的注解,可用于类或方法上。用于类上,则表示类中的所有响应请求的方法都是以该地址作为父路径。
@RequestBody:注解实现接收http请求的json数据,将json转换为java对象。
@ResponseBody:注解实现将conreoller方法返回对象转化为json对象响应给客户。
- Spring注入bean的几种方式?
JVM
- JVM的内存划分
程序计数器: 为线程私有,存储的是当前线程所执行程序的内存地址。
Java虚拟机栈:为线程私有,生命周期与线程相同。
本地方法栈:与Java虚拟机栈作用相似。
Java堆:Java虚拟机管理的最大一块内存,是线程共享的内存区域,它在虚拟机启动时创建,用于存放对象实例。
方法区:用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
运行时常量池:是方法区的一部分,存放Class文件中的符号引用等。
- 对象在内存中怎么存储的?
对象在内存中的布局分为3块区域:对象头、实例数据、对齐填充。
对象头包括标志字段(Mark Word)和类型指针(Klass Pointer)两部分信息。
实例数据存储在对象中定义的各种类型的字段内容。
对齐补充不是必然存在的,仅仅起着占位符的作用。如果实例数据不是8字节的整数倍,需要通过对其填充来补全。
- JVM在垃圾回收之前怎么判断对象是否被引用?
可达性分析算法:以GC Roots为起点向下搜索,当一个对象到GC Roots没有任何引用链相连,则判定对象是可回收的。
- 垃圾收集算法及垃圾收集器
垃圾收集算法、垃圾收集器1、CMS收集器、G1收集器
- 类加载过程
加载:通过类限定名找到字节码文件并利用字节码文件创建一个Class对象。
验证:确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。
准备:为类变量分配内存并设置类变量初始值的阶段。
解析:虚拟机将常量池内的符号引用替换为直接引用的过程。
初始化:类初始化阶段是类加载过程的最后一步,到了初始化阶段才开始执行类中定义的Java'程序代码。
redis
- redis有哪些功能
缓存、会话共享、消息队列
- redis数据类型
String(字符串)、Hash(哈希)、List(列表)、Set(集合)、zset(sorted set:有序集合)
- 缓存穿透、缓存雪崩和缓存击穿
缓存穿透,是指查询一个数据库一定不存在的数据。
缓存雪崩,是指在某一个时间段,缓存集中过期失效。
缓存击穿,是指一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库。
- 怎么保证缓存和数据库数据的一致性?
前端
- js字符串操作常用函数
concat() – 将两个或多个字符的文本组合起来,返回一个新的字符串。
indexOf() – 返回字符串中一个子串第一处出现的索引。如果没有匹配项,返回 -1 。
charAt() – 返回指定位置的字符。
lastIndexOf() – 返回字符串中一个子串最后一处出现的索引,如果没有匹配项,返回 -1 。
match() – 检查一个字符串是否匹配一个正则表达式。
substr() 函数 -- 返回从string的startPos位置,长度为length的字符串
substring() – 返回字符串的一个子串。传入参数是起始位置和结束位置。
slice() – 提取字符串的一部分,并返回一个新字符串。
replace() – 用来查找匹配一个正则表达式的字符串,然后使用新字符串代替匹配的字符串。
search() – 执行一个正则表达式匹配查找。如果查找成功,返回字符串中匹配的索引值。否则返回 -1 。
split() – 通过将字符串划分成子串,将一个字符串做成一个字符串数组。
length – 返回字符串的长度,所谓字符串的长度是指其包含的字符的个数。
toLowerCase() – 将整个字符串转成小写字母。
toUpperCase() – 将整个字符串转成大写字母。
- JavaScript中如何检测一个变量是一个String类型
typeof(obj) === "string"
typeof obj === "string"
obj.constructor === String
- 比较typeof与instanceof
typeof返回值是一个字符串,用来说明变量的数据类型。
instanceof 用于判断一个变量是否属于某个对象的实例。
- 什么是跨域?跨域请求资源的方法有哪些?
由于浏览器同源策略,凡是发送请求url的协议、域名、端口三者之间任意一与当前页面地址不同即为跨域。
CORS(后端处理)、porxy代理
jquery选择器
css盒子模型
一个元素占有空间的大小由几个部分构成,其中包括元素的内容(content),元素的内边距(padding),元素的边框(border),元素的外边距(margin)四个部分。这四个部分占有的空间中,有的部分可以显示相应的内容,而有的部分只用来分隔相邻的区域或区域。4个部分一起构成了css中元素的盒模型。行内元素有哪些?块级元素有哪些? 空(void)元素有那些?
行内元素:a、b、span、img、input、strong、select、label、em、button、textarea
块级元素:div、ul、li、dl、dt、dd、p、h1-h6、blockquote
空元素:即系没有内容的HTML元素,例如:br、meta、hr、link、input、img