Java面试宝典(自己整理+由面加点)

1  Java 基础

JVM  JRE  JDK 的区别

基本数据类型

int和Integer的区别

1、Integer是int的包装类,int则是java的一种基本数据类型

2、Integer变量必须实例化后才能使用,而int变量不需要

3、Integer实际是对象的引用,当new一个Integer时,实际上是生成一个指针指向此对象;而int则是直接存储数据值

4、Integer的默认值是null,int的默认值是0

运算符

Java中&&和&都是表示与的逻辑运算符,都表示逻辑运输符and,当两边的表达式都为true的时候,整个运算结果才为true,否则为false。

&&的短路功能,当第一个表达式的值为false的时候,则不再计算第二个表达式;&则两个表达式都执行。

&可以用作位运算符,当&两边的表达式不是Boolean类型的时候,&表示按位操作。

迭代  递推 递归

面向对象特征  

继承 封装 多态

继承 与 实现   组合  接口 抽象类

封装  private public protected   default

多态  重写 重载

五大基本原则

单一职责原则SRP(Single Responsibility Principle)是指一个类的功能要单一,不能包罗万象。如同一个人一样,分配的工作不能太多,否则一天到晚虽然忙忙碌碌的,但效率却高不起来。

开放封闭原则OCP(Open-Close Principle)一个模块在扩展性方面应该是开放的而在更改性方面应该是封闭的。比如:一个网络模块,原来只服务端功能,而现在要加入客户端功能,那么应当在不用修改服务端功能代码的前提下,就能够增加客户端功能的实现代码,这要求在设计之初,就应当将服务端和客户端分开,公共部分抽象出来。

替换原则(the Liskov Substitution Principle LSP)子类应当可以替换父类并出现在父类能够出现的任何地方。比如:公司搞年度晚会,所有员工可以参加抽奖,那么不管是老员工还是新员工,也不管是总部员工还是外派员工,都应当可以参加抽奖,否则这公司就不和谐了。

依赖原则(the Dependency Inversion Principle DIP) 具体依赖抽象,上层依赖下层。假设B是较A低的模块,但B需要使用到A的功能,这个时候,B不应当直接使用A中的具体类: 而应当由B定义一抽象接口,并由A来实现这个抽象接口,B只使用这个抽象接口:这样就达到了依赖倒置的目的,B也解除了对A的依赖,反过来是A依赖于B定义的抽象接口。通过上层模块难以避免依赖下层模块,假如B也直接依赖A的实现,那么就可能造成循环依赖。一个常见的问题就是编译A模块时需要直接包含到B模块的cpp文件,而编译B时同样要直接包含到A的cpp文件。

接口分离原则(the Interface Segregation Principle ISP)模块间要通过抽象接口隔离开,而不是通过具体的类强耦合起来


2  Java 多线程


死锁的条件  互斥  至少等待一个资源  不能被抢占   循环等待

2.1 如何开启多线程


2.2 线程如何同步 和通讯

线程同步的真实意思恰好相反,其实是“排队”。当使用多个线程来访问同一个数据时,非常容易出现线程安全问题(比如多个线程都在操作同一数据导致数据不一致),所以我们用同步机制来解决这些问题。

实现同步机制有两个方法:

同步代码块:

synchronized(同一个数据/锁){} 同一个数据:就是N条线程同时访问一个数据。

同步方法:

public synchronized 数据返回类型 方法名(){}

同步方法的同步监视器(锁)是 this 也就是该对象的本身通过使用同步方法,可非常方便的将某类变成线程安全的类。

当使用synchronized 来修饰某个共享资源时(分同步代码块和同步方法两种情况),当某个线程获得共享资源的锁后就可以执行相应的代码段,直到该线程运行完该代码段后才释放对该 共享资源的锁,让其他线程有机会执行对该共享资源的修改。当某个线程占有某个共享资源的锁时,如果另外一个线程也想获得这把锁运行就需要使用wait() 和notify()/notifyAll()方法来进行线程通讯了。

wait():导致当前线程等待,直到其他线程调用同步监视器的notify方法或notifyAll方法来唤醒该线程。

wait(mills):都是等待指定时间后自动苏醒,调用wait方法的当前线程会释放该同步监视器的锁定,可以不用notify或notifyAll方法把它唤醒。

notify():唤醒在同步监视器上等待的单个线程

notifyAll()方法:唤醒在同步监视器上等待的单个线程

作者:joshul

链接:https://www.jianshu.com/p/8081e2117258

來源:简书

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

synchronized与Lock的区别


2.3 线程如何和主线程通信

2.4线程状态

就绪(Runnable):线程准备运行,不一定立马就能开始执行。

运行中(Running):进程正在执行线程的代码。

等待中(Waiting): 线程处于阻塞的状态,等待外部的处理结束。

睡眠中(Sleeping):线程被强制睡眠。

I/O阻塞(Blocked on I/O):等待I/O操作完成。

同步阻塞(Blocked on Synchronization):等待获取锁。

死亡(Dead):线程完成了执行。


2.5 wait 和 sleep 方法的区别

① 这两个方法来自不同的类分别是,sleep来自Thread类,和wait来自Object类。

sleep是Thread的静态类方法,谁调用的谁去睡觉,即使在a线程里调用b的sleep方法,实际上还是a去睡觉,要让b线程睡觉要在b的代码中调用sleep。

② 锁: 最主要是sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。

sleep不出让系统资源;wait是进入线程等待池等待,出让系统资源,其他线程可以占用CPU。一般wait不会加时间限制,因为如果wait线程的运行资源不够,再出来也没用,要等待其他线程调用notify/notifyAll唤醒等待池中的所有线程,才会进入就绪队列等待OS分配系统资源。sleep(milliseconds)可以用时间指定使它自动唤醒过来,如果时间不到只能调用interrupt()强行打断。

Thread.sleep(0)的作用是“触发操作系统立刻重新进行一次CPU竞争”。

③ 使用范围:wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用。

synchronized(x){

x.notify()

//或者wait()

}

2.6 线程池

线程池主要解决两个问题:一方面当执行大量异步任务时候线程池能够提供较好的性能,这是因为使用线程池可以使每个任务的调用开销减少(因为线程池线程是可复用的)。另一方面线程池提供了一种资源限制和管理的手段,比如当执行一系列任务时候对线程的管理,每个ThreadPoolExecutor也保留了一些基本的统计数据,比如当前线程池完成的任务数目。

线程池状态含义:

RUNNING:接受新任务并且处理阻塞队列里的任务

SHUTDOWN:拒绝新任务但是处理阻塞队列里的任务

STOP:拒绝新任务并且抛弃阻塞队列里的任务同时会中断正在处理的任务

TIDYING:所有任务都执行完(包含阻塞队列里面任务)当前线程池活动线程为0,将要调用terminated方法

TERMINATED:终止状态。terminated方法调用完成以后的状态

线程池状态转换:

RUNNING -> SHUTDOWN

显式调用shutdown()方法,或者隐式调用了finalize(),它里面调用了shutdown()方法。

RUNNING or SHUTDOWN)-> STOP

显式 shutdownNow()方法

SHUTDOWN -> TIDYING

当线程池和任务队列都为空的时候

STOP -> TIDYING

当线程池为空的时候

TIDYING -> TERMINATED

当 terminated() hook 方法执行完成时候

阻塞队列

JDK7提供了7个阻塞队列,分别是:

ArrayBlockingQueue :由数组结构组成的有界阻塞队列。

LinkedBlockingQueue :由链表结构组成的有界阻塞队列。

PriorityBlockingQueue :支持优先级排序的无界阻塞队列。

DelayQueue:使用优先级队列实现的无界阻塞队列。

SynchronousQueue:不存储元素的阻塞队列。

LinkedTransferQueue:由链表结构组成的无界阻塞队列。

LinkedBlockingDeque:由链表结构组成的双向阻塞队列。

线程池参数:

corePoolSize:线程池核心线程个数

workQueue:用于保存等待执行的任务的阻塞队列。比如基于数组的有界ArrayBlockingQueue,基于链表的无界LinkedBlockingQueue,最多只有一个元素的同步队列SynchronousQueue,优先级队列PriorityBlockingQueue,具体可参考https://www.atatech.org/articles/81568

maximunPoolSize:线程池最大线程数量。

ThreadFactory:创建线程的工厂

RejectedExecutionHandler:饱和策略,当队列满了并且线程个数达到maximunPoolSize后采取的策略,比如AbortPolicy(抛出异常),CallerRunsPolicy(使用调用者所在线程来运行任务),DiscardOldestPolicy(调用poll丢弃一个任务,执行当前任务),DiscardPolicy(默默丢弃,不抛出异常)

keeyAliveTime:存活时间。如果当前线程池中的线程数量比核心线程数量要多,并且是闲置状态的话,这些闲置的线程能存活的最大时间

TimeUnit,存活时间的时间单位

作者:fevermxp

链接:https://www.jianshu.com/p/891dcec2c538

來源:简书

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

线程池类型

newSingleThreadExecutor

线程池中只有一个线程执行,相当于单线程.但是如果线程挂了之后(异常结束等),会重新启动一个线程替原来的线程执行下去

newFixedThreadPool

线程池的大小是固定的.每次提交一个任务就会创建一个线程,直到线程达到线程池的最大限制,里面有一个任务队列去维护未执行的任务,当有空闲的线程的时候就会到任务队列里面去取.

newCachedThreadPool

线程池中的线程是可缓存的.如果线程池的大小超过所需执行任务的大小,则系统会回收空闲线程(60秒不执行任务).当任务数增加时,线程池又可以自动添加新线程来处理任务.并且线程池不做大小的限制,线程池大小完全依赖于操作系统(或者说JVM)能够创建的最大线程大小。

newScheduledThreadPool

线程池不限大小,并且支持任务定时与周期性循环

作者:August1996

链接:https://www.jianshu.com/p/5345ab3ad78d

來源:简书

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

3  Java 集合

List Set Map

ArrayList 和 LinkedList

HashTable 和 HashMap  底实现

HashMap 底层实现  Map基于散列表的实现(取代了HashTable),插入和查询 “键值对”的开销是固定的。可以通过构造器设置容量和负载因子,调整容器的性能

LinkedList的底层数据结构 和 初始化

LinkedList底层的数据结构是基于双向循环链表的,且头结点中不存放数据,如下:


既然是双向链表,那么必定存在一种数据结构——我们可以称之为节点,节点实例保存业务数据,前一个节点的位置信息和后一个节点位置信息,如下图所示:

LinkedList提供了两个构造方法。

第一个构造方法不接受参数,将header实例的previous和next全部指向header实例(注意,这个是一个双向循环链表,如果不是循环链表,空链表的情况应该是header节点的前一节点和后一节点均为null),这样整个链表其实就只有header一个节点,用于表示一个空的链表。


执行完构造函数后,header实例自身形成一个闭环,如下图所示:


第二个构造方法接收一个Collection参数c,调用第一个构造方法构造一个空的链表,之后通过addAll将c中的元素全部添加到链表中。

AbstractList 内部方法

boolean add(E o)

将指定的元素追加到此 List 的尾部(可选操作)。

void add(int index,E element)

在此列表中指定的位置插入指定的元素(可选操作)。

boolean addAll(int index,Collection c)

void clear()

从此 collection 中移除所有元素(可选操作)。

boolean equals(Object o)

将指定的对象与此列表进行相等性比较。

abstractE get(int index)

返回此列表中指定位置处的元素。

int hashCode()

返回此列表的哈希代码值。

int indexOf(Object o)

返回此列表中首次出现指定元素的索引,如果列表中不包含此元素,则返回 -1。

Iterator iterator()

返回以正确顺序在此列表的元素上进行迭代的迭代器。

int lastIndexOf(Object o)

返回此列表中最后出现指定元素的索引,如果列表中不包含此元素,则返回 -1。

ListIterator listIterator()

返回此列表中的元素的迭代器(按适当顺序)。

ListIterator listIterator(int index)

从列表中的指定位置开始,返回此列表中的元素的列表迭代器(按适当顺序)。

E remove(int index)

移除此列表中指定位置处的元素(可选操作)。

protectedvoid removeRange(int fromIndex,int toIndex)

E set(int index,E element)

将此列表中指定位置的元素替换为指定的元素(可选操作)。

List subList(int fromIndex,int toIndex)

从类 java.util.AbstractCollection 继承的方法

addAll,contains,containsAll,isEmpty,remove,removeAll,retainAll,size,toArray,toArray,toString

从类 java.lang.Object 继承的方法

clone,finalize,getClass,notify,notifyAll,wait,wait,wait

从接口 java.util.List 继承的方法

addAll,contains,containsAll,isEmpty,remove,removeAll,retainAll,size,toArray,toArray

4  Java Web

cookies  session

http 报文

TCP 三次握手 


TCP 四次握手

TCP/IP  UDP

TCP和UDP的区别

答:

Http和Https的区别

答:

forward(转发):

1.是服务器内部的重定向,服务器直接访问目标地址的 url网址,把里面的东西读取出来,但是客户端并不知道,因此用forward的话,客户端浏览器的网址是不会发生变化的。

2.关于request: 由于在整个定向的过程中用的是同一个request,因此forward会将request的信息带到被重定向的jsp或者servlet中使用。

redirect(重定向):

1.是客户端的重定向,是完全的跳转。即服务器返回的一个url给客户端浏览器,然后客户端浏览器会重新发送一次请求,到新的url里面,因此浏览器中显示的url网址会发生变化。

2.因为这种方式比forward多了一次网络请求,因此效率会低于forward。

4.4浏览器输入网址到页面出现的过程

        1、输入网址。

  2、浏览器查找域名的IP地址。

  3. 浏览器给web服务器发送一个HTTP请求

  4. 网站服务的永久重定向响应

  5. 浏览器跟踪重定向地址 现在,浏览器知道了要访问的正确地址,所以它会发送另一个获取请求。

  6. 服务器“处理”请求,服务器接收到获取请求,然后处理并返回一个响应。

  7. 服务器发回一个HTML响应

  8. 浏览器开始显示HTML

  9. 浏览器发送请求,以获取嵌入在HTML中的对象。在浏览器显示HTML时,它会注意到需要获取其他地址内容的标签。这时,浏览器会发送一个获取请求来重新获得这些文件。这些文件就包括CSS/JS/图片等资源,这些资源的地址都要经历一个和HTML读取类似的过程。所以浏览器会在DNS中查找这些域名,发送请求,重定向等等…


4.5 拦截器和过滤器的区别

(1)过滤器:

依赖于servlet容器。在实现上基于函数回调,可以对几乎所有请求进行过滤,但是缺点是一个过滤器实例只能在容器初始化时调用一次。使用过滤器的目的是用来做一些过滤操作,获取我们想要获取的数据,比如:在过滤器中修改字符编码;在过滤器中修改HttpServletRequest的一些参数,包括:过滤低俗文字、危险字符等

作用

请求和回应的过滤,传入的request,response提前过滤掉一些信息,或者提前设置一些参数,然后再传入servlet或者struts的action进行业务逻辑,比如过滤掉非法url(不是login.do的地址请求,如果用户没有登陆都过滤掉),或者在传入servlet或者struts的action前统一设置字符集,或者去除掉一些非法字符(聊天室经常用到的,一些骂人的话)。

(2)拦截器:

依赖于web框架,在SpringMVC中就是依赖于SpringMVC框架。在实现上基于Java的反射机制,属于面向切面编程(AOP)的一种运用。由于拦截器是基于web框架的调用,因此可以使用Spring的依赖注入(DI)进行一些业务操作,同时一个拦截器实例在一个controller生命周期之内可以多次调用。但是缺点是只能对controller请求进行拦截,对其他的一些比如直接访问静态资源的请求则没办法进行拦截处理

作用

比如通过它来进行权限验证,或者判断用户是否登陆,或者是像12306 判断当前时间是否是购票时间。

区别

①拦截器是基于动态代理的,而过滤器是基于函数回调。

②拦截器不依赖于servlet容器,通过动态代理实现,过滤器依赖于servlet容器。

③拦截器可以在方法前后,异常前后等调用,而过滤器只能在请求前和请求后各调用一次。

④拦截器可以利用依赖注入,因此在Spring框架程序中,优先拦截器。

5  Java 核心

JVM的组成

JVM由4大部分组成:ClassLoader,Runtime Data Area,Execution Engine,Native Interface。

我从CSDN找了一张描述JVM大致结构的图:

1.ClassLoader是负责加载class文件,class文件在文件开头有特定的文件标示,并且ClassLoader只负责class文件的加载,至于它是否可以运行,则由Execution Engine决定。

2.Native Interface是负责调用本地接口的。他的作用是调用不同语言的接口给JAVA用,他会在Native Method Stack中记录对应的本地方法,然后调用该方法时就通过Execution Engine加载对应的本地lib。原本多于用一些专业领域,如JAVA驱动,地图制作引擎等,现在关于这种本地方法接口的调用已经被类似于Socket通信,WebService等方式取代。

3.Execution Engine是执行引擎,也叫Interpreter。Class文件被加载后,会把指令和数据信息放入内存中,Execution Engine则负责把这些命令解释给操作系统。

4.Runtime Data Area则是存放数据的,分为五部分:Stack,Heap,Method Area,PC Register,Native Method Stack。几乎所有的关于java内存方面的问题,都是集中在这块。下图是javapapers.com上关于Run-time Data Areas的描述:

可以看出它把Method Area化为了Heap的一部分,javapapers.com中认为Method Area是Heap的逻辑区域,但这取决于JVM的实现者,而HotSpot JVM中把Method Area划分为非堆内存,显然是不包含在Heap中的。下图是javacodegeeks.com中,2014年9月刊出的一片博文中关于Runtime Data Area的划分,其中指出,NonHeap包含PermGen和Code Cache,PermGen包含Method Area,而且PermGen在JAVA SE 8中已经不再用了。查阅资料(https://abhirockzz.wordpress.com/2014/03/18/java-se-8-is-knocking-are-you-there/)得知,java8中PermGen已经从JVM中移除并被MetaSpace取代,java8中也不会见到OOM:PermGen Space的异常。目前Runtime Data Area可以用下图描述它的组成:

4.1.Stack是java栈内存,它等价于C语言中的栈,栈的内存地址是不连续的,每个线程都拥有自己的栈。栈里面存储着的是StackFrame,在《JVM Specification》中文版中被译作java虚拟机框架,也叫做栈帧。StackFrame包含三类信息:局部变量,执行环境,操作数栈。局部变量用来存储一个类的方法中所用到的局部变量。执行环境用于保存解析器对于java字节码进行解释过程中需要的信息,包括:上次调用的方法、局部变量指针和操作数栈的栈顶和栈底指针。操作数栈用于存储运算所需要的操作数和结果。StackFrame在方法被调用时创建,在某个线程中,某个时间点上,只有一个框架是活跃的,该框架被称为Current Frame,而框架中的方法被称为Current Method,其中定义的类为Current Class。局部变量和操作数栈上的操作总是引用当前框架。当Stack Frame中方法被执行完之后,或者调用别的StackFrame中的方法时,则当前栈变为另外一个StackFrame。Stack的大小是由两种类型,固定和动态的,动态类型的栈可以按照线程的需要分配。 下面两张图是关于栈之间关系以及栈和非堆内存的关系基本描述(来自http://www.programering.com/a/MzM3QzNwATA.html):

4.2.Heap是用来存放对象信息的,和Stack不同,Stack代表着一种运行时的状态。换句话说,栈是运行时单位,解决程序该如何执行的问题,而堆是存储的单位,解决数据存储的问题。Heap是伴随着JVM的启动而创建,负责存储所有对象实例和数组的。堆的存储空间和栈一样是不需要连续的,它分为Young Generation和Old Generation(也叫Tenured Generation)两大部分。Young Generation分为Eden和Survivor,Survivor又分为From Space和 ToSpace。

和Heap经常一起提及的概念是PermanentSpace,它是用来加载类对象的专门的内存区,是非堆内存,和Heap一起组成JAVA内存,它包含MethodArea区(在没有CodeCache的HotSpotJVM实现里,则MethodArea就相当于GenerationSpace)。在JVM初始化的时候,我们可以通过参数来分别指定,PermanentSpace的大小、堆的大小、以及Young Generation和Old Generation的比值、Eden区和From Space的比值,从而来细粒度的适应不同JAVA应用的内存需求。

作者:大齐老师

链接:https://www.jianshu.com/p/753efd60f329

來源:简书

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

6  Java 反射和 动态代理

Java Reflaction in Action有这么一句话,可以解释。反射是运行中的程序检查自己和软件运行环境的能力,它可以根据它发现的进行改变。通俗的讲就是反射可以在运行时根据指定的类名获得类的信息。

我们为什么要使用反射,它的作用是什么,它在实际的编程中有什么应用。

首先我们先明确两个概念,静态编译和动态编译。

静态编译:在编译时确定类型,绑定对象,即通过。

动态编译:运行时确定类型,绑定对象。动态编译最大限度发挥了java的灵活性,体现了多态的应用,有以降低类之间的藕合性。

我们可以明确的看出动态编译的好处,而反射就是运用了动态编译创建对象。

7  数据库(性能调优,在线升级,结构设计,存储过程)

7.1 索引原理

7.2 存储过程

7.3 不锁表修改表字段 pt-online-schema-change mysql

7.4 事务四个特性

(1)原子性(Atomicity)

(2)一致性(Consistency)

(3)隔离性(Isolation)

(4)持久性(Durability)

7.5 事务的隔离级别

7.5.1 不事务隔离带来的问题

在介绍数据库提供的各种隔离级别之前,我们先看看如果不考虑事务的隔离性,会发生的几种问题:

更新丢失:两事务同时更新,一个失败回滚覆盖另一个事务的更新。

脏读:事务T1读取到事务T2修改了但是还未提交的数据,之后事务T2又回滚其更新操作,导致事务T1读到的是脏数据。

不可重复读:事务T1读取某个数据后,事务T2对其做了修改,当事务T1再次读该数据时得到与前一次不同的值。

虚读(幻读):事务T1读取在读取某范围数据时,事务T2又插入一条数据,当事务T1再次数据这个范围数据时发现不一样了,出现了一些“幻影行”。

不可重复读和脏读的区别:脏读是某一事务读取了另一个事务未提交的脏数据,而不可重复读则是读取了前一事务提交的数据。

幻读和不可重复读的异同:都是读取了另一条已经提交的事务(这点就脏读不同),所不同的是不可重复读查询的都是同一个数据项,而幻读针对的是一批数据整体(比如数据的个数)。

7.5.2 事务隔离的级别

●读未提交(Read Uncommitted)

含义解释:只限制同一数据写事务禁止其他写事务。解决”更新丢失”。(一事务写时禁止其他事务写

名称解释:可读取未提交数据

所需的锁:排他写锁

●读提交(Read Committed)

含义解释:只限制同一数据写事务禁止其它读写事务。解决”脏读”,以及”更新丢失”。(一事务写时禁止其他事务读写

名称解释:必须提交以后的数据才能被读取

所需的锁:排他写锁、瞬间共享读锁

●可重复读(Repeatable Read)

含义解释:限制同一数据写事务禁止其他读写事务,读事务禁止其它写事务(允许读)。解决”不可重复读”,以及”更新丢失”和”脏读”。(一事务写时禁止其他事务读写、一事务读时禁止其他事务写)

注意没有解决幻读,解决幻读的方法是增加范围锁(range lock)或者表锁。

名称解释:能够重复读取

所需的锁:排他写锁、共享读锁

●串行化(Serializable)

提供严格的事务隔离。它要求事务序列化执行,事务只能一个接着一个地执行,但不能并发执行。如果仅仅通过“行级锁”是无法实现事务序列化的,必须通过其他机制保证新插入的数据不会被刚执行查询操作的事务访问到。(一事务写时禁止其他事务读写、一事务读时禁止其他事务读写

限制所有读写事务都必须串行化实行。

7.6 Hibernate 事务缓存

Hibernate中提供了两级缓存,一级缓存是Session级别的缓存,它属于事务范围的缓存,该级缓存由hibernate管理,应用程序无需干预;二级缓存是SessionFactory级别的缓存,该级缓存可以进行配置和更改,并且可以动态加载和卸载,hibernate还为查询结果提供了一个查询缓存,它依赖于二级缓存;

7.6.1 Hibernate中的第一级缓存

Hibernate的一级缓存由Session提供,只存在于Session的生命周期中,当应用程序调用Session接口的save(),update(),saveOrupDate(),get(),load()或者Query和Criteria实例的list(),iterate()等方法时,如果Session缓存中没有相应的对象,hibernate就会把对象加入到一级缓存中,当session关闭时,该Session所管理的一级缓存也会立即被清除;

7.6.2 Hibernate中的第二级缓存

二级缓存是一个可插拔的缓存插件,它是由SessionFactory负责管理的;

由于SessionFactory对象的生命周期与应用程序的整个过程对应,通常一个应用程序对应一个SessionFactory,因此,二级缓存是进程范围或者集群范围的缓存;

与一级缓存一样,二级缓存也是根据对象的id来加载与缓存,当执行某个查询获得结果集为实体对象集时,hibernate就会把它们按照对象id加载到二级缓存中,在访问指定的id的对象时,首先从一级缓存中查找,找到就直接使用,找不到则转到二级缓存中查找(必须配置且启用二级缓存),如果二级缓存中找到,则直接使用,否则会查询数据库,并将查询结果根据对象的id放到缓存中;

7.7 懒加载 

标签  fetch = FetchType.LAZY

1、FetchType.LAZY:懒加载,加载一个实体时,定义懒加载的属性不会马上从数据库中加载。

2、FetchType.EAGER:急加载,加载一个实体时,定义急加载的属性会立即从数据库中加载。

8  缓存 REDIS

8.1 基本数据类型

String Hash List  Set  Sorted Set

8.2 为什么用Redis

1) 减轻内存压力

2)易扩展  不需要固定模式

3)提高大数据读取性能

4)数据模式相对灵活

5)原子性操作

8.3 List的数据结构

List数据结构是链表结构,这意味这无论数据量多大,头尾操作数据还是很快的,list的容量是2的32次方减1个元素,即4294967295个元素数量

8.4 判断 set 中是否存在某个元素

SISMEMBER key member

判断 member 元素是否是集合 key 的成员

9  Spring AOP IOC MVC

9.1 AOP 面向切面  基于JAVA的动态代理


9.2 IOC 基于Java的反射


9.3 MVC 核心类

DispatcherServlet  -- 前置控制器

HandlerMapping接口 -- 处理请求的映射

HandlerMapping接口的实现类:

SimpleUrlHandlerMapping  通过配置文件,把一个URL映射到Controller

DefaultAnnotationHandlerMapping  通过注解,把一个URL映射到Controller类上

HandlerAdapter接口 -- 处理请求的映射

AnnotationMethodHandlerAdapter类,通过注解,把一个URL映射到Controller类的方法上

Controller接口 -- 控制器 由于我们使用了@Controller注解,添加了@Controller注解注解的类就可以担任控制器(Action)的职责,

HandlerInterceptor 接口--拦截器

ViewResolver接口的实现类

UrlBasedViewResolver类 通过配置文件,把一个视图名交给到一个View来处理

InternalResourceViewResolver类,比上面的类,加入了JSTL的支持

9.4 springmvc常用注解标签详解

@Controller

@RequestMapping

@Resource和@Autowired

@ModelAttribute和 @SessionAttributes

@PathVariable

@requestParam

@ResponseBody

@Component

@Repository


9.5 Spring注解@Resource和@Autowired区别对比

@Resource和@Autowired都是做bean的注入时使用,其实@Resource并不是Spring的注解,它的包是javax.annotation.Resource,需要导入,但是Spring支持该注解的注入。

1、共同点

两者都可以写在字段和setter方法上。两者如果都写在字段上,那么就不需要再写setter方法。

2、不同点

(1)@Autowired

@Autowired为Spring提供的注解,需要导入包org.springframework.beans.factory.annotation.Autowired;只按照byType注入。

publicclass TestServiceImpl {

    // 下面两种@Autowired只要使用一种即可    @Autowired

    privateUserDao userDao;// 用于字段上   

    @Autowired

    publicvoidsetUserDao(UserDao userDao) {// 用于属性的方法上this.userDao = userDao;

    }

}

@Autowired注解是按照类型(byType)装配依赖对象,默认情况下它要求依赖对象必须存在,如果允许null值,可以设置它的required属性为false。如果我们想使用按照名称(byName)来装配,可以结合@Qualifier注解一起使用。如下:

publicclass TestServiceImpl {

    @Autowired

    @Qualifier("userDao")

    private UserDao userDao;

}

(2)@Resource

@Resource默认按照ByName自动注入,由J2EE提供,需要导入包javax.annotation.Resource。@Resource有两个重要的属性:name和type,而Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。所以,如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果既不制定name也不制定type属性,这时将通过反射机制使用byName自动注入策略。

publicclass TestServiceImpl {

    // 下面两种@Resource只要使用一种即可@Resource(name="userDao")

    privateUserDao userDao;// 用于字段上   

    @Resource(name="userDao")

    publicvoidsetUserDao(UserDao userDao) {// 用于属性的setter方法上this.userDao = userDao;

    }

}

注:最好是将@Resource放在setter方法上,因为这样更符合面向对象的思想,通过set、get去操作属性,而不是直接去操作属性。

@Resource装配顺序:

①如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常。

②如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常。

③如果指定了type,则从上下文中找到类似匹配的唯一bean进行装配,找不到或是找到多个,都会抛出异常。

④如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配。

@Resource的作用相当于@Autowired,只不过@Autowired按照byType自动注入。

10 Linux 命令

10.1  awk  (词频  平均值) 

egrep -o "\b[[:alpha:]]+\b" $filename | \

awk '{ count[$0]++ }

END{ printf("%-14s%s\n","Word","Count") ;

for(ind in count)

{ printf("%-14s%d\n",ind,count[ind]); }

}'

10.2  进程处理  ps -ef |grep   

ps -f | grep java | grep -e grep | awk '{print $2}' | xargs kill -9

10.3  最大文件

du -s * | sort -n | tail      查找当前路径下最大的文件  sort -n  以数字排序  tail  显示行尾10行

du -s * | sort -nr | head                                                    -nr 以数字倒序  head  显示行首10行

11 Java新特性

11.1 Java6 新特性

引入了一个支持脚本引擎的新框架

UI的增强

对WebService支持的增强(JAX-WS2.0和JAXB2.0)

一系列新的安全相关的增强

JDBC4.0

Compiler API

通用的Annotations支持

11.2 Java7 新特性

switch中可以使用字串了

运用List tempList = new ArrayList<>(); 即泛型实例化类型自动推断

语法上支持集合,而不一定是数组

新增一些取环境信息的工具方法

Boolean类型反转,空指针安全,参与位运算

两个char间的equals

安全的加减乘除

map集合支持并发请求,且可以写成 Map map = {name:"xxx",age:18};

11.3 Java 8 新特性

Lambda 表达式 ? Lambda允许把函数作为一个方法的参数(函数作为参数传递进方法中。

方法引用 ? 方法引用提供了非常有用的语法,可以直接引用已有Java类或对象(实例)的方法或构造器。与lambda联合使用,方法引用可以使语言的构造更紧凑简洁,减少冗余代码。

默认方法 ? 默认方法就是一个在接口里面有了一个实现的方法。Java 8允许我们给接口添加一个非抽象的方法实现,只需要使用 default关键字即可,这个特征又叫做扩展方法,

新工具 ? 新的编译工具,如:Nashorn引擎 jjs、 类依赖分析器jdeps。

Stream API ?新添加的Stream API(java.util.stream) 把真正的函数式编程风格引入到Java中。

Date Time API ? 加强对日期与时间的处理。

Optional 类 ? Optional 类已经成为 Java 8 类库的一部分,用来解决空指针异常。

Nashorn, JavaScript 引擎 ? Java 8提供了一个新的Nashorn javascript引擎,它允许我们在JVM上运行特定的javascript应用。

12. SVN 和GIT

12.1  SVN优缺点

优点:

1、 管理方便,逻辑明确,符合一般人思维习惯。

2、 易于管理,集中式服务器更能保证安全性。

3、 代码一致性非常高。

4、 适合开发人数不多的项目开发。

缺点:

1、 服务器压力太大,数据库容量暴增。

2、 如果不能连接到服务器上,基本上不可以工作,看上面第二步,如果服务器不能连接上,就不能提交,还原,对比等等。

3、 不适合开源开发(开发人数非常非常多,但是Google app engine就是用svn的)。但是一般集中式管理的有非常明确的权限管理机制(例如分支访问限制),可以实现分层管理,从而很好的解决开发人数众多的问题。

12.2 Git优缺点

优点:

1、适合分布式开发,强调个体。

2、公共服务器压力和数据量都不会太大。

3、速度快、灵活。

4、任意两个开发者之间可以很容易的解决冲突。

5、离线工作。

缺点:

1、学习周期相对而言比较长。

2、不符合常规思维。

3、代码保密性差,一旦开发者把整个库克隆下来就可以完全公开所有代码和版本信息。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,596评论 18 139
  • 从三月份找实习到现在,面了一些公司,挂了不少,但最终还是拿到小米、百度、阿里、京东、新浪、CVTE、乐视家的研发岗...
    时芥蓝阅读 42,178评论 11 349
  • 最近互联网金融是热点中的热点,当前互联网金融格局,以p2p为代表的借贷平台、以众筹为代表的股权投资平台,以...
    国金社阅读 393评论 0 0
  • sliro阅读 143评论 0 0
  • 仍然很难有人相信。即使今天,在中国的沿海一带还会有这样的地方。 我来自大连下辖的一个农村,是个挺穷的地方,甚至现...
    阿泰逗你玩阅读 575评论 0 51