JAVA基础面试题

Hibernate的缓存机制
一、Hibernate是一个持久层框架,常常访问物理数据库,为了下降应用程序对物理数据源访问的频次,从而提升应用程序的运行性能。
缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事件会同步缓存和物理数据源的数据。
二、Hibernate一级缓存又称为“Session的缓存”,它是内置的,不能被卸载(不能被卸载的意思就是这种缓存不具备可选性,
必须有的功能,不能够取消session缓存)。
因为Session对象的生命周期一般对应一个数据库事务或者一个应用事务,所以它的缓存是事务范围的缓存。
三、Hibernate二级缓存又称为“SessionFactory的缓存”,因为SessionFactory对象的生命周期和应用程序的整个过程对应,
所以Hibernate二级缓存是进程范围或者集群范围的缓存,有可能出现并发问题,所以须要采用适当的并发访问策略,
该策略为被缓存的数据提供了事务隔离级别。
四、不管什么时候,咱们在管理Hibernate缓存(Managing the caches)时,当你给save()、update()或saveOrUpdate()方法传递一个对象时,
或使用load()、 get()、list()、iterate() 或scroll()方法得到一个对象时, 该对象都将被加入到Session的内部缓存中。前端

二、什么是线程,线程和进程的区别 ,java如何实现线程
线程是操做系统可以进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运做单位。java

区别:线程是进程的子集,一个进程能够有不少线程,每条线程并行执行不一样的任务。不一样的进程使用不一样的内存空间,而全部的线程共享一片相同的内存空间。每一个线程都拥有单独的栈内存用来存储本地数据。程序员

实现线程:继承Thread或实现Runnable接口 ;这两种方法都能实现线程 区别是 java 不支持类的多重继承, 但容许调用多个接口,若是要继承其余类 只能调用Runnable接口算法

三、 Thread 类中的start() 和 run() 方法有什么区别?
start()方法被用来启动新建立的线程,并且start内部调用了run()方法,这和直接调用run()方法的效果不同。当你调用run()方法的时候,
只会是在原来的线程中调用,没有新的线程启动,start()方法才会启动新线程。数据库

四、Java中的volatile 变量是什么?
volatile是一个特殊的修饰符,只有成员变量才能使用它。在Java并发程序缺乏同步类的状况下,多线程对成员变量的操做对其它线程是透明的。
volatile变量能够保证下一个读取操做会在前一个写操做以后发生 编程


五、什么是线程安全?Vector是一个线程安全类吗?
若是你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。若是每次运行结果和单线程运行的结果是同样的,并且其余的变量的值也和预期的是同样的,就是线程安全的。一个线程安全的计数器类的同一个实例对象在被多个线程使用的状况下也不会出现计算失误。
Vector 是用同步方法来实现线程安全的, 而和它类似的ArrayList不是线程安全的。设计模式

六、Java中如何中止一个线程?
Java提供了很丰富的API但没有为中止线程提供API。
JDK 1.0原本有一些像stop(), suspend() 和 resume()的控制方法可是因为潜在的死锁威胁所以在后续的JDK版本中他们被弃用了,
以后Java API的设计者就没有提供一个兼容且线程安全的方法来中止一个线程。
当run() 或者 call() 方法执行完的时候线程会自动结束,若是要手动结束一个线程,你能够用volatile 布尔变量来退出run()方法的循环或者是取消任务来中断线程。数组

七、一个线程运行时发生异常会怎样?
若是异常没有被捕获该线程将会中止执行。Thread.UncaughtExceptionHandler是用于处理未捕获异常形成线程忽然中断状况的一个内嵌接口。
当一个未捕获异常将形成线程中断的时候JVM会使用Thread.getUncaughtExceptionHandler()来查询线程的UncaughtExceptionHandler并将线程和异常做为参数传递给handler的uncaughtException()方法进行处理。缓存


八、Java中notify 和 notifyAll有什么区别?
由于多线程能够等待单监控锁,Java API 的设计人员提供了一些方法当等待条件改变的时候通知它们,可是这些方法没有彻底实现。
notify()方法不能唤醒某个具体的线程,因此只有一个线程在等待的时候它才有用武之地。
而notifyAll()唤醒全部线程并容许他们争夺锁确保了至少有一个线程能继续运行。安全


九、为何wait, notify 和 notifyAll这些方法不在thread类里面?
一个很明显的缘由是JAVA提供的锁是对象级的而不是线程级的,每一个对象都有锁,经过线程得到。
若是线程须要等待某些锁那么调用对象中的wait()方法就有意义了。若是wait()方法定义在Thread类中,线程正在等待的是哪一个锁就不明显了。
简单的说,因为wait,notify和notifyAll都是锁级别的操做,因此把他们定义在Object类中由于锁属于对象。

十、Java中的同步集合与并发集合有什么区别?
 同步集合与并发集合都为多线程和并发提供了合适的线程安全的集合,不过并发集合的可扩展性更高。
并发集合像ConcurrentHashMap,不只提供线程安全还用锁分离和内部分区等现代技术提升了可扩展性。

十一、Java中堆和栈有什么不一样?
每一个线程都有本身的栈内存,用于存储本地变量,方法参数和栈调用,一个线程中存储的变量对其它线程是不可见的。
而堆是全部线程共享的一片公用内存区域。对象都在堆里建立,为了提高效率线程会从堆中弄一个缓存到本身的栈,若是多个线程使用该变量就可能引起问题,这时volatile 变量就能够发挥做用了,它要求线程从主存中读取变量的值。

十二、什么是线程池? 为何要使用它?
建立线程要花费昂贵的资源和时间,若是任务来了才建立线程那么响应时间会变长,并且一个进程能建立的线程数有限。
为了不这些问题,在程序启动的时候就建立若干线程来响应处理,它们被称为线程池,里面的线程叫工做线程。从JDK1.5开始,Java API提供了Executor框架让你能够建立不一样的线程池。好比单线程池,每次处理一个任务;数目固定的线程池或者是缓存线程池(一个适合不少生存期短的任务的程序的可扩展线程池)。

1三、如何避免死锁?
  Java多线程中的死锁死锁是指两个或两个以上的进程在执行过程当中,因争夺资源而形成的一种互相等待的现象,若无外力做用,它们都将没法推动下去。
死锁的发生必须知足如下四个条件:
互斥条件:一个资源每次只能被一个进程使用。
请求与保持条件:一个进程因请求资源而阻塞时,对已得到的资源保持不放。
不剥夺条件:进程已得到的资源,在末使用完以前,不能强行剥夺。
循环等待条件:若干进程之间造成一种头尾相接的循环等待资源关系。
避免死锁最简单的方法就是阻止循环等待条件,将系统中全部的资源设置标志位、排序,规定全部的进程申请资源必须以必定的顺序(升序或降序)作操做来避免死锁。

1四、 Java中活锁和死锁有什么区别?
  这是上题的扩展,活锁和死锁相似,不一样之处在于处于活锁的线程或进程的状态是不断改变的,活锁能够认为是一种特殊的饥饿。一个现实的活锁例子是两我的在狭小的走廊碰到,两我的都试着避让对方好让彼此经过,可是由于避让的方向都同样致使最后谁都不能经过走廊。简单的说就是,活锁和死锁的主要区别是前者进程的状态能够改变可是却不能继续执行。


1五、怎么检测一个线程是否拥有锁?
在java.lang.Thread中有一个方法叫holdsLock(),当且仅当当前线程拥有某个具体对象的锁它返回true。

1六、有三个线程T1,T2,T3,怎么确保它们按顺序执行?
  在多线程中有多种方法让线程按特定顺序执行,你能够用线程类的join()方法在一个线程中启动另外一个线程,另一个线程完成该线程继续执行。为了确保三个线程的顺序你应该先启动最后一个(T3调用T2,T2调用T1),这样T1就会先完成而T3最后完成。

1七、 Java线程池中submit() 和 execute()方法有什么区别?
  两个方法均可以向线程池提交任务,execute()方法的返回类型是void,它定义在Executor接口中, 而submit()方法能够返回持有计算结果的Future对象,它定义在ExecutorService接口中,它扩展了Executor接口,其它线程池类像ThreadPoolExecutor和ScheduledThreadPoolExecutor都有这些方法。

1八、什么是阻塞式方法?
  阻塞式方法是指程序会一直等待该方法完成期间不作其余事情,ServerSocket的accept()方法就是一直等待客户端链接。这里的阻塞是指调用结果返回以前,当前线程会被挂起,直到获得结果以后才会返回。此外,还有异步和非阻塞式方法在任务完成前就返回。

1九、多线程中的忙循环是什么?
  忙循环就是程序员用循环让一个线程等待,不像传统方法wait(), sleep() 或 yield() 它们都放弃了CPU控制,而忙循环不会放弃CPU,它就是在运行一个空循环。这么作的目的是为了保留CPU缓存,在多核系统中,一个等待线程醒来的时候可能会在另外一个内核运行,这样会重建缓存。为了不重建缓存和减小等待重建的时间就可使用它了。

20、若是同步块内的线程抛出异常会发生什么?
不管你的同步块是正常仍是异常退出的,里面的线程都会释放锁,因此对比锁接口我更喜欢同步块,由于它不用我花费精力去释放锁,
该功能能够在finally block里释放锁实现。

2一、Java多线程中调用wait() 和 sleep()方法有什么不一样?
  Java程序中wait 和 sleep都会形成某种形式的暂停,它们能够知足不一样的须要。
wait()方法用于线程间通讯,若是等待条件为真且其它线程被唤醒时它会释放锁,而sleep()方法仅仅释放CPU资源或者让当前线程中止执行一段时间,
但不会释放锁。

 

2二、数据库的优化
一、硬件优化,提升机器性能,增长硬件等;
二、优化查询语句,将限定性强的where条件放前,用exists代替in操做等;
三、优化索引,创建有效的索引并检查和修复缺乏的统计信息等
四、数据库系统文件优化,将数据文件、索引文件、日志文件放置在不一样的磁盘上,提升并行度等
五、大数据分割,当一个表的数据规模达到数亿条时,索引已基本发挥不了做用:创建索引要花费大量时间,查询时因为要扫描大的索引表也要花费大量时间。为了发挥索引的做用,能够将大表按照某个字段拆分为若干个小表。


2三、抽象类(abstract class)和接口(interface)有什么异同?
答:抽象类和接口都不可以实例化,但能够定义抽象类和接口类型的引用。一个类若是继承了某个抽象类或者实现了某个接口都须要对其中的抽象方法所有进行实现,不然该类仍然须要被声明为抽象类。接口比抽象类更加抽象,由于抽象类中能够定义构造器,能够有抽象方法和具体方法,而接口中不能定义构造器并且其中的方法所有都是抽象方法。抽象类中的成员能够是private、默认、protected、public的,而接口中的成员全都是public的。抽象类中能够定义成员变量,而接口中定义的成员变量实际上都是常量。有抽象方法的类必须被声明为抽象类,而抽象类未必要有抽象方法


2四、阐述final、finally、finalize的区别。
答:
- final:修饰符(关键字)有三种用法:若是一个类被声明为final,意味着它不能再派生出新的子类,即不能被继承,所以它和abstract是反义词。将变量声明为final,能够保证它们在使用中不被改变,被声明为final的变量必须在声明时给定初值,而在之后的引用中只能读取不可修改。被声明为final的方法也一样只能使用,不能在子类中被重写。
- finally:一般放在try…catch…的后面构造老是执行代码块,这就意味着程序不管正常执行仍是发生异常,这里的代码只要JVM不关闭都能执行,能够将释放外部资源的代码写在finally块中。
- finalize:Object类中定义的方法,Java中容许使用finalize()方法在垃圾收集器将对象从内存中清除出去以前作必要的清理工做。这个方法是由垃圾收集器在销毁对象时调用的,经过重写finalize()方法能够整理系统资源或者执行其余清理工做。

2五、阐述ArrayList、Vector、LinkedList的存储性能和特性。
答:ArrayList和Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增长和插入元素,它们都容许直接按序号索引元素,可是插入元素要涉及数组元素移动等内存操做,因此索引数据快而插入数据慢,Vector中的方法因为添加了synchronized修饰,所以Vector是线程安全的容器,但性能上较ArrayList差,所以已是Java中的遗留容器。LinkedList使用双向链表实现存储(将内存中零散的内存单元经过附加的引用关联起来,造成一个能够按序号索引的线性结构,这种链式存储方式与数组的连续存储方式相比,内存的利用率更高),按序号索引数据须要进行前向或后向遍历,可是插入数据时只须要记录本项的先后项便可,因此插入速度较快。Vector属于遗留容器(Java早期的版本中提供的容器,除此以外,Hashtable、Dictionary、BitSet、Stack、Properties都是遗留容器),已经不推荐使用,可是因为ArrayList和LinkedListed都是非线程安全的,若是遇到多个线程操做同一个容器的场景,则能够经过工具类Collections中的synchronizedList方法将其转换成线程安全的容器后再使用(这是对装潢模式的应用,将已有对象传入另外一个类的构造器中建立新的对象来加强实现)。

2六、List、Map、Set三个接口存取元素时,各有什么特色?
答:List以特定索引来存取元素,能够有重复元素。Set不能存放重复元素(用对象的equals()方法来区分元素是否重复)。Map保存键值对(key-value pair)映射,映射关系能够是一对一或多对一。Set和Map容器都有基于哈希存储和排序树的两种实现版本,基于哈希存储的版本理论存取时间复杂度为O(1),而基于排序树版本的实如今插入或删除元素时会按照元素或元素的键(key)构成排序树从而达到排序和去重的效果。

2七、TreeMap和TreeSet在排序时如何比较元素?Collections工具类中的sort()方法如何比较元素?
答:TreeSet要求存放的对象所属的类必须实现Comparable接口,该接口提供了比较元素的compareTo()方法,当插入元素时会回调该方法比较元素的大小。TreeMap要求存放的键值对映射的键必须实现Comparable接口从而根据键对元素进行排序。Collections工具类的sort方法有两种重载的形式,第一种要求传入的待排序容器中存放的对象比较实现Comparable接口以实现元素的比较;第二种不强制性的要求容器中的元素必须可比较,可是要求传入第二个参数,参数是Comparator接口的子类型(须要重写compare方法实现元素的比较),至关于一个临时定义的排序规则,其实就是经过接口注入比较元素大小的算法,也是对回调模式的应用(Java中对函数式编程的支持)。

2八、Java中如何实现序列化,有什么意义?
答:序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。能够对流化后的对象进行读写操做,也可将流化后的对象传输于网络之间。序列化是为了解决对象流读写操做时可能引起的问题(若是不进行序列化可能会存在数据乱序的问题)。
要实现序列化,须要让一个类实现Serializable接口,该接口是一个标识性接口,标注该类对象是可被序列化的,而后使用一个输出流来构造一个对象输出流并经过writeObject(Object)方法就能够将实现对象写出(即保存其状态);若是须要反序列化则能够用一个输入流创建对象输入流,而后经过readObject方法从流中读取对象。序列化除了可以实现对象的持久化以外,还可以用于对象的深度克隆


2九、简述一下你了解的设计模式。


工厂模式:工厂类能够根据条件生成不一样的子类实例,这些子类有一个公共的抽象父类而且实现了相同的方法,可是这些方法针对不一样的数据进行了不一样的操做(多态方法)。当获得子类的实例后,开发人员能够调用基类中的方法而没必要考虑到底返回的是哪个子类的实例。
- 代理模式:给一个对象提供一个代理对象,并由代理对象控制原对象的引用。实际开发中,按照使用目的的不一样,代理能够分为:远程代理、虚拟代理、保护代理、Cache代理、防火墙代理、同步化代理、智能引用代理。


30、JSP有哪些内置对象?做用分别是什么?
答:JSP有9个内置对象:
- request:封装客户端的请求,其中包含来自GET或POST请求的参数;
- response:封装服务器对客户端的响应;
- pageContext:经过该对象能够获取其余对象;
- session:封装用户会话的对象;
- application:封装服务器运行环境的对象;
- out:输出服务器响应的输出流对象;
- config:Web应用的配置对象;
- page:JSP页面自己(至关于Java程序中的this);
- exception:封装页面抛出异常的对象。


3一、get和post请求的区别?
答:
①get请求用来从服务器上得到资源,而post是用来向服务器提交数据;
②get将表单中数据按照name=value的形式,添加到action 所指向的URL 后面,而且二者使用"?"链接,而各个变量之间使用"&"链接;post是将表单中的数据放在HTTP协议的请求头或消息体中,传递到action所指向URL;
③get传输的数据要受到URL长度限制(1024字节);而post能够传输大量的数据,上传文件一般要使用post方式;
④使用get时参数会显示在地址栏上,若是这些数据不是敏感数据,那么可使用get;对于敏感数据仍是应用使用post;
⑤get使用MIME类型application/x-www-form-urlencoded的URL编码(也叫百分号编码)文本的格式传递参数,保证被传送的参数由遵循规范的文本组成,例如一个空格的编码是"%20"。


3二、讲解JSP中的四种做用域。
答:JSP中的四种做用域包括page、request、session和application,具体来讲:
- page表明与一个页面相关的对象和属性。
- request表明与Web客户机发出的一个请求相关的对象和属性。一个请求可能跨越多个页面,涉及多个Web组件;须要在页面显示的临时数据能够置于此做用域。
- session表明与某个用户与服务器创建的一次会话相关的对象和属性。跟某个用户相关的数据应该放在用户本身的session中。
- application表明与整个Web应用程序相关的对象和属性,它实质上是跨越整个Web应用程序,包括多个页面、请求和会话的一个全局做用域

 

3三、Hibernate中Session的load和get方法的区别是什么?
答:主要有如下三项区别:
① 若是没有找到符合条件的记录,get方法返回null,load方法抛出异常。
② get方法直接返回实体类对象,load方法返回实体类对象的代理。
③ 在Hibernate 3以前,get方法只在一级缓存中进行数据查找,若是没有找到对应的数据则越过二级缓存,直接发出SQL语句完成数据读取;load方法则能够从二级缓存中获取数据;从Hibernate 3开始,get方法再也不是对二级缓存只写不读,它也是能够访问二级缓存的。


3四、Hibernate如何实现分页查询?
答:经过Hibernate实现分页查询,开发人员只须要提供HQL语句(调用Session的createQuery()方法)或查询条件(调用Session的createCriteria()方法)、设置查询起始行数(调用Query或Criteria接口的setFirstResult()方法)和最大查询行数(调用Query或Criteria接口的setMaxResults()方法),并调用Query或Criteria接口的list()方法,Hibernate会自动生成分页查询的SQL语句


3五、解释一下什么叫AOP(面向切面编程)?
答:AOP(Aspect-Oriented Programming)指一种程序设计范型,该范型以一种称为切面(aspect)的语言构造为基础,切面是一种新的模块化机制,用来描述分散在对象、类或方法中的横切关注点(crosscutting concern)

3六、Spring MVC的工做原理是怎样的?
答:Spring MVC的工做原理以下图所示:

① 客户端的全部请求都交给前端控制器DispatcherServlet来处理,它会负责调用系统的其余模块来真正处理用户的请求。
②DispatcherServlet收到请求后,将根据请求的信息(包括URL、HTTP协议方法、请求头、请求参数、Cookie等)以及HandlerMapping的配置找处处理该请求的Handler(任何一个对象均可以做为请求的Handler)。
③在这个地方Spring会经过HandlerAdapter对该处理器进行封装。
④ HandlerAdapter是一个适配器,它用统一的接口对各类Handler中的方法进行调用。
⑤ Handler完成对用户请求的处理后,会返回一个ModelAndView对象给DispatcherServlet,ModelAndView顾名思义,包含了数据模型以及相应的视图的信息。
⑥ ModelAndView的视图是逻辑视图,DispatcherServlet还要借助ViewResolver完成从逻辑视图到真实视图对象的解析工做。
⑦ 当获得真正的视图对象后,DispatcherServlet会利用视图对象对模型数据进行渲染。
⑧ 客户端获得响应,多是一个普通的HTML页面,也能够是XML或JSON字符串,还能够是一张图片或者一个PDF文件。

 


3七、选择使用Spring框架的缘由(Spring框架为企业级开发带来的好处有哪些)?
答:能够从如下几个方面做答:
- 非侵入式:支持基于POJO的编程模式,不强制性的要求实现Spring框架中的接口或继承Spring框架中的类。
- IoC容器:IoC容器帮助应用程序管理对象以及对象之间的依赖关系,对象之间的依赖关系若是发生了改变只须要修改配置文件而不是修改代码,由于代码的修改可能意味着项目的从新构建和完整的回归测试。有了IoC容器,程序员不再须要本身编写工厂、单例,这一点特别符合Spring的精神”不要重复的发明轮子”。
- AOP(面向切面编程):将全部的横切关注功能封装到切面(aspect)中,经过配置的方式将横切关注功能动态添加到目标代码上,进一步实现了业务逻辑和系统服务之间的分离。另外一方面,有了AOP程序员能够省去不少本身写代理类的工做。
- MVC:Spring的MVC框架是很是优秀的,从各个方面均可以甩Struts 2几条街,为Web表示层提供了更好的解决方案。
- 事务管理:Spring以宽广的胸怀接纳多种持久层技术,而且为其提供了声明式的事务管理,在不须要任何一行代码的状况下就可以完成事务管理。
- 其余:选择Spring框架的缘由还远不止于此,Spring为Java企业级开发提供了一站式选择,你能够在须要的时候使用它的部分和所有,更重要的是,你甚至能够在感受不到Spring存在的状况下,在你的项目中使用Spring提供的各类优秀的功能。

 

3八、阐述Spring框架中Bean的生命周期?
答:
① Spring IoC容器找到关于Bean的定义并实例化该Bean。
② Spring IoC容器对Bean进行依赖注入。
③ 若是Bean实现了BeanNameAware接口,则将该Bean的id传给setBeanName方法。
④ 若是Bean实现了BeanFactoryAware接口,则将BeanFactory对象传给setBeanFactory方法。
⑤ 若是Bean实现了BeanPostProcessor接口,则调用其postProcessBeforeInitialization方法。
⑥ 若是Bean实现了InitializingBean接口,则调用其afterPropertySet方法。
⑦ 若是有和Bean关联的BeanPostProcessors对象,则这些对象的postProcessAfterInitialization方法被调用。
⑧ 当销毁Bean实例时,若是Bean实现了DisposableBean接口,则调用其destroy方法。

16二、依赖注入时如何注入集合属性?答:能够在定义Bean属性时,经过<list> / <set> / <map> / <props>分别为其注入列表、集合、映射和键值都是字符串的映射属性。

相关文章
相关标签/搜索