java中级面试题
1、Java中堆和栈有什么不同?
每个线程都有自己的栈内存,用于存储本地变量,方法参数和栈调用,一个线程中存储的变量对其它线程是不可见的。而堆是所有线程共享的一片公用内存区域。对象都在堆里创建,为了提升效率线程会从堆中弄一个缓存到自己的栈,如果多个线程使用该变量就可能引发问题,这时volatile 变量就可以发挥作用了,它要求线程从主存中读取变量的值。
堆:(对象)
引用类型的变量,其内存分配在堆上或者常量池(字符串常量、基本数据类型常量),需要通过new等方式来创建。
堆内存主要作用是存放运行时创建(new)的对象。
(主要用于存放对象,存取速度慢,可以运行时动态分配内存,生存期不需要提前确定)
栈:(基本数据类型变量、对象的引用变量)
基本数据类型的变量(int、short、long、byte、float、double、boolean、char等)以及对象的引用变量,其内存分配在栈上,变量出了作用域就会自动释放。
2、Spring的Scope有以下几种,通过@Scope注解来实现:
(1)Singleton:一个Spring容器中只有一个Bean的实例,此为Spring的默认配置,全容器共享一个实例。
(2)Prototype:每次调用新建一个Bean实例。
(3)Request:Web项目中,给每一个 http request 新建一个Bean实例。
(4)Session:Web项目中,给每一个 http session 新建一个Bean实例。
(5)GlobalSession:这个只在portal应用中有用,给每一个 global http session 新建一个Bean实例。
5、Spring事务传播行为
所谓事务的传播行为是指,如果在开始当前事务之前,一个事务上下文已经存在,此时有若干选项可以指定一个事务性方法的执行行为。在TransactionDefinition定义中包括了如下几个表示传播行为的常量:
TransactionDefinition.PROPAGATION_REQUIRED:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。这是默认值。
TransactionDefinition.PROPAGATION_REQUIRES_NEW:创建一个新的事务,如果当前存在事务,则把当前事务挂起。
TransactionDefinition.PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起。
TransactionDefinition.PROPAGATION_NEVER:以非事务方式运行,如果当前存在事务,则抛出异常。
TransactionDefinition.PROPAGATION_MANDATORY:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。
TransactionDefinition.PROPAGATION_NESTED:如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED。
6、Spring的声明式事务管理力度是什么级别?
Struts2是类级别的,Spring是方法级别的
spring事务可以分为编程式事务和声明式事务
7、spring MVC与struts2的区别:
参考: http://blog.csdn.net/chenleixing/article/details/44570681
① Struts2是类级别的拦截, 一个类对应一个request上下文,SpringMVC是方法级别的拦截
② SpringMVC的方法之间基本上独立的,独享request response数据
③ 由于Struts2需要针对每个request进行封装,把request,session等servlet生命周期的变量封装成一个一个Map,供给每个Action使用,并保证线程安全,所以在原则上,是比较耗费内存的
④ 拦截器实现机制上,Struts2有以自己的interceptor机制,SpringMVC用的是独立的AOP方式
⑤ SpringMVC的入口是servlet,而Struts2是filter
⑥ SpringMVC集成了Ajax
⑦ SpringMVC验证支持JSR303,处理起来相对更加灵活方便,而Struts2验证比较繁琐,感觉太烦乱
⑧ Spring MVC和Spring是无缝的。从这个项目的管理和安全上也比Struts2高
⑨ Struts2更加符合OOP的编程思想, SpringMVC就比较谨慎,在servlet上扩展
⑩ SpringMVC开发效率和性能高于Struts2
8、ArrayList和LinkedList的大致区别如下:
1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。
2.对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。
3.对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。
9、ArrayList,Vector主要区别为以下几点:
(1):Vector是线程安全的,源码中有很多的synchronized可以看出,而ArrayList不是。导致Vector效率无法和ArrayList相比;
(2):ArrayList和Vector都采用线性连续存储空间,当存储空间不足的时候,ArrayList默认增加为原来的50%,Vector默认增加为原来的一倍;
10、HashSet与HashMap的区别:
11、HashMap和Hashtable的区别:
HashMap和Hashtable都实现了Map接口,但决定用哪一个之前先要弄清楚它们之间的分别。主要的区别有:线程安全性,同步(synchronization),以及速度。
- HashMap几乎可以等价于Hashtable,除了HashMap是非synchronized的,并可以接受null(HashMap可以接受为null的键值(key)和值(value),而Hashtable则不行)。
- HashMap是非synchronized,而Hashtable是synchronized,这意味着Hashtable是线程安全的,多个线程可以共享一个Hashtable;而如果没有正确的同步的话,多个线程是不能共享HashMap的。Java 5提供了ConcurrentHashMap,它是HashTable的替代,比HashTable的扩展性更好。
- 另一个区别是HashMap的迭代器(Iterator)是fail-fast迭代器,而Hashtable的enumerator迭代器不是fail-fast的。所以当有其它线程改变了HashMap的结构(增加或者移除元素),将会抛出ConcurrentModificationException,但迭代器本身的remove()方法移除元素则不会抛出ConcurrentModificationException异常。但这并不是一个一定发生的行为,要看JVM。这条同样也是Enumeration和Iterator的区别。
- 由于Hashtable是线程安全的也是synchronized,所以在单线程环境下它比HashMap要慢。如果你不需要同步,只需要单一线程,那么使用HashMap性能要好过Hashtable。
- HashMap不能保证随着时间的推移Map中的元素次序是不变的。
13、Spring Bean的生命周期:
- Bean的建立, 由BeanFactory读取Bean定义文件,并生成各个实例
- Setter注入,执行Bean的属性依赖注入
- BeanNameAware的setBeanName(), 如果实现该接口,则执行其setBeanName方法
- BeanFactoryAware的setBeanFactory(),如果实现该接口,则执行其setBeanFactory方法
- BeanPostProcessor的processBeforeInitialization(),如果有关联的processor,则在Bean初始化之前都会执行这个实例的processBeforeInitialization()方法
- InitializingBean的afterPropertiesSet(),如果实现了该接口,则执行其afterPropertiesSet()方法
- Bean定义文件中定义init-method
- BeanPostProcessors的processAfterInitialization(),如果有关联的processor,则在Bean初始化之前都会执行这个实例的processAfterInitialization()方法
- DisposableBean的destroy(),在容器关闭时,如果Bean类实现了该接口,则执行它的destroy()方法
- Bean定义文件中定义destroy-method,在容器关闭时,可以在Bean定义文件中使用“destory-method”定义的方法
简单回答springbean生命周期:
(1)实例化(必须的)构造函数构造对象
(2)装配(可选的)为属性赋值
(3)回调(可选的)(容器-控制类和组件-回调类)
(4)初始化(init-method=" ")
(5)就绪
(6)销毁(destroy-method=" ")
15、springmvc生命周期:
1A)客户端发出http请求,只要请求形式符合web.xml
文件中配置的*.action的话,就由DispatcherServlet
来处理。
1B)DispatcherServlet再将http请求委托给映射器
的对象来将http请求交给对应的Action来处理
2)映射器根据客户的http请求,再对比 垃圾回收器在对堆进行回收之前,需要确定堆中哪些对象是可以继续存活的,哪些是可以被回收的,Java采用可达性分析算法来判定对象是否可以继续存活。 这个算法的过程是通过一系列的称为“GC Roots”的对象作为起点,从这些起始点开始向下搜索,搜索过程中所有走过的路径称为引用链,当一个对象和引用链没任何连接的时候,则表明这个对象是可以被回收的。 可作为“GC Roots”对象的有如下几种: Java虚拟机栈(栈帧中的本地变量表)中引用的对象; 本地方法栈中JNI(即一般说的Native方法)引用的对象; 方法区中类静态属性引用的对象; 方法区中常量引用的对象。 还有一个用于标识哪些对象可以被回收的算法,不过这个算法并没有被Java语言采用,即引用计数法。这个算法的过程是:给每个对象添加一个引用计数器,每当这个对象被引用一次,计数器加一;每当这个对象引用失效的时候,计数器减一;引用计数器为零的对象表示是可以被回收的对象。虽然这个算法很简单,但是它无法解决对象之间互相循环引用的问题,所以Java没有采用。5.数据库隔离级别
多个事务读可能会道理以下问题
脏读:事务B读取事务A还没有提交的数据
不可重复读:,一行被检索两次,并且该行中的值在不同的读取之间不同时
幻读:当在事务处理过程中执行两个相同的查询,并且第二个查询返回的行集合与第一个查询不同时
这两个区别在于,不可重复读重点在一行,幻读的重点 ,返回 的集合不一样
6 JVM
Git与SVN的区别(面试常问)
1、Git是分布式的,而SVN不是分布式的
2、Git把内容按元数据方式存储,而SVN是按文件
3、Git没有一个全局版本号,SVN有,目前为止这是SVN相比Git缺少的最大的一个特征
4、Git的内容的完整性要优于SVN: GIT的内容存储使用的是SHA-1哈希算法。这能确保代码内容的完整性,确保在遇到磁盘故障和网络问题时降低对版本库的破坏
5、Git下载下来后,在OffLine状态下可以看到所有的Log,SVN不可以
6、SVN必须先Update才能Commit,忘记了合并时就会出现一些错误,git还是比较少的出现这种情况
7、克隆一份全新的目录以同样拥有五个分支来说,SVN是同时复製5个版本的文件,也就是说重复五次同样的动作。而Git只是获取文件的每个版本的 元素,然后只载入主要的分支(master)在我的经验,克隆一个拥有将近一万个提交(commit),五个分支,每个分支有大约1500个文件的 SVN,耗了将近一个小时!而Git只用了区区的1分钟
8、版本库(repository):SVN只能有一个指定中央版本库。当这个中央版本库有问题时,所有工作成员都一起瘫痪直到版本库维修完毕或者新的版本库设立完成。而 Git可以有无限个版本库。或者,更正确的说法,每一个Git都是一个版本库,区别是它们是否拥有活跃目录(Git Working Tree)。如果主要版本库(例如:置於GitHub的版本库)发生了什麼事,工作成员仍然可以在自己的本地版本库(local repository)提交,等待主要版本库恢复即可。工作成员也可以提交到其他的版本库
9、
分支(Branch)在SVN,分支是一个完整的目录。且这个目录拥有完整的实际文件。如果工作成员想要开啟新的分支,那将会影响“全世界”!每个人都会拥有和你一样的分支。如果你的分支是用来进行破坏工作(安检测试),那将会像传染病一样,你改一个分支,还得让其他人重新切分支重新下载,十分狗血。而 Git,每个工作成员可以任意在自己的本地版本库开啟无限个分支。举例:当我想尝试破坏自己的程序(安检测试),并且想保留这些被修改的文件供日后使用, 我可以开一个分支,做我喜欢的事。完全不需担心妨碍其他工作成员。只要我不合并及提交到主要版本库,没有一个工作成员会被影响。等到我不需要这个分支时, 我只要把它从我的本地版本库删除即可。无痛无痒。
Git的分支名是可以使用不同名字的。例如:我的本地分支名为OK,而在主要版本库的名字其实是master。
最值得一提,我可以在Git的任意一个提交点(commit point)开启分支!(其中一个方法是使用gitk –all 可观察整个提交记录,然后在任意点开啟分支。)
10、提交(Commit)在SVN,当你提交你的完成品时,它将直接记录到中央版本库。当你发现你的完成品存在严重问题时,你已经无法阻止事情的发生了。如果网路中断,你根本没办法提交!而Git的提交完全属於本地版本库的活动。而你只需“推”(git push)到主要版本库即可。Git的“推”其实是在执行“同步”(Sync)