default关键字
接口中可以定义默认实现方法和静态方法,通常我们认为接口里只能有抽象方法,不能有任何方法发的实现,但是使用default修饰的方法可以在接口里自定义内容。
Lambda表达式
函数式接口
方法与构造参数引用
局部变量限制
Date Api更新
流
对Map的数据结构进行了优化
为HashMap加入了红黑树,使得查询更加的快速。
总结:上界不存,下界不取
只能输入限定类型本身与其子类
只能输入限定类型本身与其父类
#==&equals
#HashMap&HashTable&ConcurrentHashMap
HashTable
HashMap
数据结构:
初始大小:16 Size
自动扩容:newSize = oldSize * 2(每次扩容后原来数组中的元素需要重新计算排列)
允许一个null键和多个null值
线程不安全
效率高
ConcurrentHashMap
哈希冲突
若干Key的哈希值按数组大小取模后,如果落在同一个槽点上,就会组成一条Entry链,在查找时通过遍历Entry链上的每个元素使用equals()方法进行比较。
加载因子
为了降低哈希冲突的概率,默认当HashMap中的键值对数量达到数组长度的75%,就会触发自动扩容。
空间换时间
如果希望加快查询速度,可以降低加载因子,增大初始大小,以降低哈希冲突的概率。
共有属性
Properties(Java.util.Properties)主要用于读取Java的配置文件。
9大内置对象:
4大域:
实现会话跟踪的技术有哪些?
使用Cookie
向客户端发送Cookie:
Cookie c =new Cookie("name","value"); //创建Cookie
c.setMaxAge(60*60*24); //设置最大时效,此处设置的最大时效为一天
response.addCookie(c); //把Cookie放入到HTTP响应中
从客户端读取Cookie:
String name ="name";
Cookie[]cookies =request.getCookies();
if(cookies !=null){
for(int i= 0;i<cookies.length;i++){
Cookie cookie =cookies[i];
if(name.equals(cookis.getName()))
//something is here.
//you can get the value
cookie.getValue();
}
}
URL重写
隐藏的表单域
优点:cookie被禁用依然可用
缺点:所有页面必须是表单提交之后的结果
HttpSession
单例设计模式
单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中,应用该模式的类一个类只有一个实例。即一个类只有一个对象实例。
具体实现:
饿汉式单例
懒汉式单例
定义一个静态方法返回这个唯一对象。
将构造方法私有化,使其不能在类的外部通过new关键字实例化该类对象。
在该类内部产生一个唯一的实例化对象,并且将其封装为private static类型。
饿汉模式/立即加载:
public class Singleton {
// 将自身实例化对象设置为一个属性,并用static、final修饰
private static final Singleton instance = new Singleton();
// 构造方法私有化
private Singleton() { }
// 静态方法返回该实例
public static Singleton getInstance() {
return instance;
}
}
懒汉模式/延迟加载:
public class Singleton {
// 将自身实例化对象设置为一个属性,并用static修饰
private static Singleton instance;
// 构造方法私有化
private Singleton() {}
// 静态方法返回该实例
public static Singleton getInstance() {
if(instance == null) {
instance = new Singleton();
}
return instance;
}
}
工厂设计模式
工厂设计模式,就是用来生产对象的,在java中,万物皆对象,这些对象都需要创建,如果创建的时候直接new该对象,就会对该对象耦合严重,假如我们要更换对象,所有new对象的地方都需要修改一遍,这显然违背了软件设计的开闭原则,如果我们使用工厂来生产对象,我们就只和工厂打交道就可以了,彻底和对象解耦,如果要更换对象,直接在工厂里更换该对象即可,达到了与对象解耦的目的;所以说,工厂模式最大的优点就是:解耦
简单工厂
定义:一个工厂方法,依据传入的参数,生成对应的产品对象。
角色:
1、抽象产品
2、具体产品
3、具体工厂
4、产品使用者
使用说明:先将产品类抽象出来,比如,苹果和梨都属于水果,抽象出来一个水果类Fruit,苹果和梨就是具体的产品类,然后创建一个水果工厂,分别用来创建苹果和梨。
水果接口
public interface Fruit {
void whatIm();
}
实现类 苹果
public class Apple implements Fruit {
@Override
public void whatIm() {
//苹果
}
}
实现类 梨
public class Pear implements Fruit {
@Override
public void whatIm() {
//梨
}
}
工厂类 水果工厂
public class FruitFactory {
public Fruit createFruit(String type) {
if (type.equals("apple")) {//生产苹果
return new Apple();
} else if (type.equals("pear")) {//生产梨
return new Pear();
}
return null;
}
}
产品试用者
FruitFactory mFactory = new FruitFactory();
Apple apple = (Apple) mFactory.createFruit("apple");//获得苹果
Pear pear = (Pear) mFactory.createFruit("pear");//获得梨
总结:以上的这种方式,每当我想添加一种水果,就必然要修改工厂类,这显然违反了开闭原则,亦不可取;所以简单工厂只适合于产品对象较少,且产品固定的需求,对于产品变化无常的需求来说显然不合适。
工厂方法
定义:将工厂提取成一个接口或抽象类,具体生产什么产品由子类决定;
角色:
抽象产品类
具体产品类
抽象工厂类
具体工厂类
使用说明:和上例中一样,产品类抽象出来,这次我们把工厂类也抽象出来,生产什么样的产品由子类来决定。
水果接口 苹果类和梨类 代码和上例一样 。
工厂接口
public interface FruitFactory {
Fruit createFruit();//生产水果
}
苹果工厂
public class AppleFactory implements FruitFactory {
@Override
public Fruit createFruit() {
return new Apple();
}
}
梨工厂
public class PearFactory implements FruitFactory {
@Override
public Fruit createFruit() {
return new Pear();
}
}
使用
AppleFactory appleFactory = new AppleFactory();
PearFactory pearFactory = new PearFactory();
Apple apple = (Apple) appleFactory.createFruit();//获得苹果
Pear pear = (Pear) pearFactory.createFruit();//获得梨
总结:以上这种方式,虽然解耦了,也遵循了开闭原则,但是问题根本还是没有解决啊,换汤没换药,如果我需要的产品很多的话,需要创建非常多的工厂,所以这种方式的缺点也很明显。
抽象工厂
定义:为创建一组相关或者是相互依赖的对象提供的一个接口,而不需要指定它们的具体类。
角色:和工厂方法一样
使用说明:抽象工厂和工厂方法的模式基本一样,区别在于,工厂方法是生产一个具体的产品,而抽象工厂可以用来生产一组相同,有相对关系的产品;重点在于一组,一批,一系列;举个例子,假如生产小米手机,小米手机有很多系列,小米note、红米note等;假如小米note生产需要的配件有825的处理器,6英寸屏幕,而红米只需要650的处理器和5寸的屏幕就可以了。
cpu接口和实现类
public interface Cpu {
void run();
class Cpu650 implements Cpu {
@Override
public void run() {
//625 也厉害
}
}
class Cpu825 implements Cpu {
@Override
public void run() {
//825 处理更强劲
}
}
}
屏幕接口和实现类
public interface Screen {
void size();
class Screen5 implements Screen {
@Override
public void size() {
//5寸
}
}
class Screen6 implements Screen {
@Override
public void size() {
//6寸
}
}
}
工厂接口
public interface PhoneFactory {
Cpu getCpu();//使用的cpu
Screen getScreen();//使用的屏幕
}
具体工厂实现类:小米手机工厂
public class XiaoMiFactory implements PhoneFactory {
@Override
public Cpu getCpu() {
return new Cpu.Cpu825();//高性能处理器
}
@Override
public Screen getScreen() {
return new Screen.Screen6();//6寸大屏
}
}
具体工厂实现类:红米手机工厂
public class HongMiFactory implements PhoneFactory {
@Override
public Cpu getCpu() {
return new Cpu.Cpu650();//高效处理器
}
@Override
public Screen getScreen() {
return new Screen.Screen5();//小屏手机
}
}
总结:以上例子可以看出,抽象工厂可以解决一系列的产品生产的需求,对于大批量,多系列的产品,用抽象工厂可以更好的管理和扩展。
1、对于简单工厂和工厂方法来说,两者的使用方式实际上是一样的,如果对于产品的分类和名称是确定的,数量是相对固定的,推荐使用简单工厂模式;
2、抽象工厂用来解决相对复杂的问题,适用于一系列、大批量的对象生产;
数据库事务的特点
一持隔原
事务并发处理带来的问题
隔离级别
线程的6种状态
新建(New)
当新创建出来一个线程,但是这个线程还没有开始运行时。
可运行(Runnable)
一旦调用了start方法,则该线程处于可运行状态,在这个状态下,它有可能在运行,也有可能没有运行,具体取决于是否抢到CPU的使用权。
被阻塞(Blocked)
当一个线程视图获取一个内部对象的锁时,而该锁被其他对象持有,这时就进入了被阻塞状态。
等待(Waiting)
当线程等待另一个线程通知调度器一个条件时,它自己进入等待状态。在调用 Object.wait 方法或 Thread.join 方法, 或者是等待 java,util.concurrent 库中的 Lock 或 Condition 时, 就会出现这种情况。实际上,被阻塞状态
与等待状态是有很大不同的。
计时等待(Timed waiting)
有几个方法有一个超时参数。调用它们导致线程进人计时等待( timed waiting ) 状态。这一状态将一直保持到超时期满或者接收到适当的通知。带有超时参数的方法有Thread.sleep 和 Object.wait、Thread.join、 Lock,tryLock 以及 Condition.await 的计时版。
终止(Terminated)
ThreadPoolExport
线程池创建方式有几种
Redis是一个用C语言开发,并且开源的Key-Value数据库。是一种NoSql(非关系型)数据库。
数据类型
数据持久化
快照(RDB):存储数据
RDB 是 Redis 默认的持久化方案。在指定的时间间隔内,执行指定次数的写操作,则会将内存中的数据写入到磁盘中。即在指定目录下生成一个dump.rdb文件。Redis 重启会通过加载dump.rdb文件恢复数据。
体积小,恢复快,但数据完整性和一致性不高。
日志文件(AOF):存储(写)命令
AOF :Redis 默认不开启。它的出现是为了弥补RDB的不足(数据的不一致性),所以它采用日志的形式来记录每个写操作,并追加到文件中。Redis 重启的会根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。
体积大,恢复慢,数据完整性高。
混合模式(4.0版本支持):RDB+AOF
先以RDB模式存储全量数据,再已AOF存储新增数据。
Redis的并发竞争问题如何解决?
什么是缓存穿透?
缓存穿透就是当有很大的并发量在缓存中没有查到数据而去数据库查询,就会给数据库造成很大7的压力,这就叫缓存穿透。
关键词:缓存value为空;并发量很大去访问DB。
造成的原因。
业务代码出现问题,或数据出现问题,或者是一些恶意攻击。
解决方案。
如果一个查询返回的数据为空,不管是数据不存在还是系统故障,我们仍然把这个结果进行缓存,但是它的过期时间会很短最长不超过5分钟。
什么时缓存击穿
缓存击穿即使在某一时间节点有大量的并发查询去查询同一条数据,而这条数据刚好过期,所以去查数据库,从而会对数据库造成很大的压力。
关键词:缓存没有查到,从而大量请求去查询同一条数据。
造成的原因
某一Key刚好过期,但是却刚好有大量请求来查询这条数据。
解决方案
互斥锁
设置热点数据永不过期。
什么是缓存雪崩?
雪崩就是当有很大的并发量去请求缓存时,造成了缓存服务器的崩溃,从而使大量请求去查询数据库,使得数据库也可能会挂掉,这就叫做雪崩。
关键词:缓存挂掉,大量并发去访问数据库,从而使数据库也可能会挂掉。
造成的原因
当在某一个时间节点有大量的缓存失效,这样在失效的时候,大量数据访问就会直接访问数据库,给数据库造成很大的压力。
解决方案
什么是Redis,简述它的优缺点?
MySQL里有2000w数据,redis中只存20w的数据,如何保证redis中的数据都是热点数据?
Redis的内存数据集数量达到一定大小,它会自动执行数据淘汰策略。
Redis有哪些适合的场景?
会话缓存
全页缓存
队列
Reids在内存存储引擎领域的一大优点是提供 list 和 set 操作,这使得Redis能作为一个很好的消息队列平台来使用。Redis作为队列使用的操作,就类似于本地程序语言(如Python)对 list 的 push/pop 操作。
排行榜/计数器
发布/订阅
说说Redis哈希槽的概念?
Redis集群没有一致性的Hash,而是引入了哈希槽的概念,redis集群一共有16384个哈希槽,每个key通过对16384取模来确定放在哪个槽,集群的每个节点都负责一部分槽。
Redis集群的主从复制模型是怎样的?
每个节点都会有N-1个复制品。
Redis集群会有写操作丢失吗?为什么?
redis不能保证数据的一致性,所以可能发生写操作丢失。
Redis集群之间是如何复制的?
异步复制。
Redis集群最大节点个数是多少?
16384个。
Redis集群如何选择数据库?
Redis集群目前无法做数据库选择,默认在0数据库。
怎么理解Redis事务?
事务是一个单独的隔离操作,事务中的命令都会序列化,按顺序的执行,事务在执行过程中不会被其他指令所打断。
引擎
Sql优化
如何定位并优化慢Sql
show variables like '%quer%';
set global slow_query_log = on; # 开启慢Sql日志记录
set global long_query_time = 1; #定义慢Sql的超时时间 单位:(秒)
explain
工具分析Sql
explain
字段。修改Sql或尽量让Sql走索引
show profile分析
索引
数据库三大范式
AOP(面向切面编程)
IOC(控制反转)
DI(依赖注入)
事务的传播行为
7种 指定事务如何传播
配置
执行流程
什么是Spring MVC ?简单介绍下你对springMVC的理解?
Spring MVC是一个基于Java的,并且实现了MVC设计模式的一种轻量级Web框架,通过把Model,Veiw,Controller分离,将Web层进行解耦,使得开发人员简化开发,减少出错。
Spring MVC执行流程
Springmvc的优点:
Spring MVC的主要组件?
(1)前端控制器 DispatcherServlet(不需要程序员开发)
作用:接收请求、响应结果,相当于转发器,有了DispatcherServlet 就减少了其它组件之间的耦合度。
(2)处理器映射器HandlerMapping(不需要程序员开发)
作用:根据请求的URL来查找Handler
(3)处理器适配器HandlerAdapter
注意:在编写Handler的时候要按照HandlerAdapter要求的规则去编写,这样适配器HandlerAdapter才可以正确的去执行Handler。
(4)处理器Handler(需要程序员开发)
(5)视图解析器 ViewResolver(不需要程序员开发)
作用:进行视图的解析,根据视图逻辑名解析成真正的视图(view)
(6)视图View(需要程序员开发jsp)
View是一个接口, 它的实现类支持不同的视图类型(jsp,freemarker,pdf等等)
SpringMVC怎么样设定重定向和转发的?
SpringMVC怎么和AJAX相互调用的?
加入Jackson.jar
在配置文件中配置json的映射
在接受Ajax方法里面可以直接返回Object,List等,但方法前面要加上@ResponseBody注解。
如何解决POST请求中文乱码问题,GET的又如何处理呢?
Spring MVC的异常处理 ?
SpringMvc的控制器是不是单例模式,如果是,有什么问题,怎么解决?
SpringMVC常用的注解有哪些?
SpingMvc中的控制器的注解一般用那个,有没有别的注解可以替代?
如果在拦截请求中,我想拦截get方式提交的方法,怎么配置?
怎样在方法里面得到Request,或者Session?
如果想在拦截的方法里面得到从前台传入的参数,怎么得到?
如果前台有很多个参数传入,并且这些参数都是一个对象的,那么怎么样快速得到这个对象?
SpringMvc中函数的返回值是什么?
SpringMvc用什么对象从后台向前台传递数据的?
怎么样把ModelMap里面的数据放入Session里面?
SpringMvc里面拦截器是怎么写的:
有两种写法,一种是实现HandlerInterceptor接口,另外一种是继承适配器类,接着在接口方法当中,实现处理逻辑;然后在SpringMvc的配置文件中配置拦截器即可:
<mvc:interceptors>
<bean id="myInterceptor" class="com.zwp.action.MyHandlerInterceptor">bean>
<mvc:interceptor>
<mvc:mapping path="/modelMap.do" />
<bean class="com.zwp.action.MyHandlerInterceptorAdapter" />
mvc:interceptor>
mvc:interceptors>
注解原理:
Hibernate一级缓存与二级缓存的区别
Hibernate中**get()和load()**方法的区别
实现方式:Spring Security + CAS
单点登录流程:
服务与服务之间进行异步通信。
问:Active MQ的消息是被顺序接受的吗?如果不是,如何确保消息会被顺序接收?
答:不是被顺序接收,如果需要顺序接受可以给每一个消息加上时间戳,让消息具有时序性.
ThreadLocal
JVM是一个内存中的虚拟机
反射机制:java的反射机制是在运行状态中可以获取任意一个类或者任意一个对象的任意属性和任意方法,这种动态调用对象的功能称为Java语言的反射机制。
Class Loader:ClassLoader可以将class文件里的数据加载到JVM虚拟机。
双亲委派模型:
如果一个类加载器收到类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器完成。每个类加载器都是如此,只有当父加载器在自己的搜索范围内找不到指定的类时(即ClassNotFoundException
),子加载器才会尝试自己去加载。
为什么使用双亲委派机制加载类:
JVM内存模型(JDK8)
线程私有:
线程共享:
JVM三大性能调优参数-Xms -Xmx -Xss的含义?
Java内存模型中堆和栈的区别?
Java垃圾回收机制
对象被判定为垃圾的标准——这个东西没有了价值
引用计数算法——判断对象的引用数量。
通过判断对象的引用数量来决定对象是否可以被回收。
每个对象实例都有一个引用计数器,被引用 +1 ,引用结束 -1 。
任何引用计数器为0的对象实例都可以被当作垃圾收集。
**优点:**执行效率高,程序执行受影响小。
缺点:无法检测出循环引用情况,会导致内存泄漏。
谈谈你了解的垃圾回收算法
标记—清除算法(Mark and Sweep)
总结:会造成内存碎片化
复制算法(Copying)—— 适合新生代
总结:
解决碎片化问题。
顺序分配内存,简单高效。
适用于对象存活率低的场景。
标记—整理算法(Compacting)——适合老年代
总结:
分代收集算法(Generational Collector )
垃圾回收算法的组合拳
按照对象生命周期的不同划分区域,以采用不同的垃圾回收算法
目的:提高JVM的回收效率
JDK7:年轻代,老年代,永久代
JDK8:
GC的分类
Minor GC
发生在年轻代的垃圾回收动作,使用复制算法。
Full GC
发生在老年代的垃圾回收动作,在执行之前也会执行Minor GC,使用标记清理算法或标记整理算法。
年轻代:尽可能的快速回收掉那些生命周期短的对象(所占堆空间:1/3)
对象如何晋升到老年代
常用的调优参数
老年代:存放生命周期较长的对象(所占堆空间:2/3)
Error和Exception的区别
从责任角度看:
常见Error以及Exception
Runtime Exception:
非Runtime Exception:
Error:
NoClassDefoundError - 找不到class定义的异常
成因:
StackOverflowError - 深递归导致栈被耗尽而抛出的异常
OutOfMemoryError - 内存溢出异常
Java的异常处理机制
抛出异常:创建异常对象,交由运行时系统处理
捕获异常:寻找合适的异常处理器处理异常,否则终止运行
Java异常的处理原则
高效主流的异常处理框架
设计一个通用的继承自RuntimeException的异常类来统一处理
其余异常都统一转译为上述异常AppException
在Catch之后,抛出上述异常的子类,并提供注意定位的信息
由前端接收AppException做统一处理
Spring中的所有异常都可以用org. springframework.core.Nested. RuntimeException来表示