Java基础
1.String类为什么是不可变的?为什么是final的?
什么是不可变:定义一个字符串对象,再新建一个对象赋值给这个字符串,这个赋值过程不是修改原地址的数据,而是指向一个新的对象,这就叫不可变。如下图:
JDK源码里,String类被final修饰,String类有一个属性是char类型的数组,说明String类本质上是一个数组,这个数组也被final修饰,所以String类不可变。好处有:
- 线程安全--String对象不可变,不能被写入,所以在多线程中修改字符串的值,其他的引用指向的还是原来的对象,不会被改变。
- 用于实现StringPool--栈里面的多个引用可以指向StringPool里的同一个字符串,节省了很多堆空间,如果String是可变的,那StringPool就没有意义了。
- 便于计算哈希值-- 因为String类不可变,所以字符串很适合被hash。String类有一个hashCode()方法用于计算哈希值,在创建字符串的时候哈希值就计算出来并被缓存了,不需要重新计算。这就使得字符串很适合作为Map中的键,处理速度要快过其它的键对象。
补充:
- String类中有个私有实例字段hash,表示该字符串的哈希值。
- hash值的计算过程,是依据被hash的值的特征计算的,这要求被hash的值必须固定,因此被hash的值必须不可变。
2.HashMap的源码分析,实现原理,底层结构?
- 底层结构:
HashMap是由数组+链表+红黑树组成的。数组是主体,存放的是Entry对象(Entry有四个属性:key、value、hash、next),向数组的某个位置插入一个entry对象的时候,如果发生哈希冲突,就把那个位置的entry对象作为头结点,指向要插入的entry对象,形成一个单向链表。但是链表不擅长查询,所以链表越少,HashMap的性能越好。在JDK1.8里引入了红黑树,当链表长度超过8的时候,就转换成红黑树来存储元素,提高HashMap的性能。
实现原理:
先用key通过哈希函数计算出一个数组索引,如果索引位置没有元素就直接放进去,如果有元素,若key相同就直接替换,若key不相同就遍历索引位置的链表,把元素插入链表。如果链表长度大于8,就转换成红黑树来存储元素。
源码分析:
补充:https://www.cnblogs.com/chengxiao/p/6059914.html
3.反射中,Class.forName(String name)和ClassLoader的区别?
反射:动态地获取类的内容,并映射成一个Java对象。
Java中Class.forName(String name)和ClassLoader都可用来对类进行加载,获得字节码文件。
- Class.forName(String name)将类的字节码文件加载到JVM中,内部调用的forName()方法里有一个参数是控制初始化的,是true,所以会初始化,会加载静态代码块。
- ClassLoader只是将字节码文件加载到JVM中,不会加载静态代码块。只有在用newInstance创建对象的时候才会加载静态代码块。
数据库加载驱动使用Class.forName(String name),是因为DriverManager驱动类有静态代码块。
4.session和cookie的区别和联系,session的生命周期,多个服务部署时session管理。
Cookie:数据存储在客户端,安全性不好,客户端可以删除cookie。如果不设置持久化时间,cookie会存储在浏览器的内存中,浏览器关闭,cookie信息销毁,如果设置持久化时间,cookie会被持久化到磁盘文件里。
Session:数据存储在服务器端,安全性较好,但当session太多时会占用部分服务器资源,session需要借助cookie来存储JSESSIONID。session默认30分钟过期,也可以通过配置更改这个时间。
SOA架构中,单点登录系统,专门使用一台服务器来保存session信息,用redis模拟session,用uuid模拟JSESSIONID。
补充:
https://my.oschina.net/u/3943244/blog/1929801
https://my.oschina.net/u/3943244/blog/2992047#h4_9
5.Java中的队列都有哪些,有什么区别。
- 双端队列Deque:队列两端都可以进行入队出队操作
- 阻塞队列BlockingQueue:如果BlockQueue是空的,这时如果有线程要从这个BlockingQueue取元素,将会被阻塞进入等待状态,直到别的线程在BlockingQueue中添加进了元素,被阻塞的线程才会被唤醒。同样,如果BlockingQueue是满的,试图往队列中存放元素的线程也会被阻塞进入等待状态,直到BlockingQueue里的元素被别的线程拿走才会被唤醒继续操作
- 非阻塞队列AbstractQueue:多个线程存取元素时,直接返回结果,不具有阻塞的特点。
补充:
https://zhuanlan.zhihu.com/p/53076263
6.Java的内存模型以及GC算法
线程共享:Java堆,方法区
线程私有:程序计数器,Java虚拟机栈,本地方法栈
现代虚拟机中的GC(垃圾收集)算法:
- 标记-清除算法
标记:遍历所有的节点,然后将所有可以到达GC Root的对象标记为存活的对象。
清除:遍历堆中所有的对象,将没有标记的对象全部清除掉。
效率低,清理出来的内存是不连续的,适合大量对象存活的情况 - 复制算法
将内存按照容量分为大小相等的两块,每次只使用其中一块,当这一块内存用完了,把还在存活的对象复制到另一块内存上,清空当前使用的内存块,去使用另一块。(商业应用中,8:1)
空间利用率低,存活对象多的时候效率低,适合少量对象存活的情况。 - 标记-整理算法
从GC Root开始遍历所有节点,对所有存活的对象做一次标记,之后,将所有的存活对象压缩到内存的一端,然后清理其他所有的空间。
从效率上来说,标记-整理算法要低于复制算法(不仅要标记所有存活对象,还要整理所有存活对象的引用地址).
适合存活对象较多的情况。 - 分代收集算法
将Java堆分为老年代和新生代,根据对象的存活时间不同,将内存划分为几块,分别采用针对性的GC算法,提高效率。新生代:少量对象存活,使用复制算法。
老年代:大量对象存活,适合用标记-清除/标记-整理算法
补充:
GC Root:对象之间的引用组成了一张图,其中有一个叫做GC Root的根节点,如果一个对象不能到达根节点,说明这个对象已经失效。
标记-清除算法、复制算法、标记-整理算法的总结:三个算法都基于根搜索算法去判断一个对象是否应该被回收。
JVM详解
Field类详解
Native方法详解
GC
GC结构图
7.JDK7、JDK8的新特性
JDK7:
- 数值类型字面值可以用‘多个‘_’分隔增加可读性
- 可以使用字符串控制switch语句
- try语句里声明的资源,可以自动关闭
- 多重捕获异常(multi-catch),本来不同的异常是由多个catch语句块来处理,现在可以把多个异常用一个catch语句块来处理,用’|’来表示多个异常,也就是或的意思
JDK8:
- 接口中可以添加static方法,接口中可以为方法添加默认实现。
原来的接口:接口中的成员变量默认(必须)都是public、static、final类型的,必须被显式初始化;接口中的方法默认(必须)都是public、abstract类型的。
https://blog.csdn.net/zhaojianting/article/details/80338273
8.Java数组和链表两种结构的操作效率,在哪些情况下,哪些操作(查询、插入删除)的效率高?
数组是一组地址连续、长度固定的内存空间,链表是动态分配内存,内存地址可以连续可以不连续,随机查询操作数组效率更高(O(1)),插入和删除操作链表效率更高(O(1))
9.Java内存泄露的问题调查定位:jmap,jstack的使用等等
- jps:主要用来输出JVM中运行的进程状态信息
- jstack:主要用来查看某个Java进程内的线程栈信息
- jmap用来查看堆内存使用状况
补充:
https://blog.csdn.net/sinat_29581293/article/details/70214436
http://www.importnew.com/28916.html
Java开发框架
1.spring框架中需要引用哪些jar包,以及这些jar包的用途
- spring-core.jar:包含Spring 框架基本的核心工具类,其它组件要都要使用到这个包里的类,依赖Commons Logging(Log4J)。
- spring-beans.jar:是所有组件都要用到的,它包含访问配置文件、创建和管理bean 以及进行IOC、DI操作相关的所有类。依赖spring-core(CGLIB)。
- spring-aop.jar:包含在应用中使用AOP 特性时所需的类。
- spring-aspects.jar:提供对AspectJ的支持,以便可以方便的将面向切面的功能集成进IDE中,比如Eclipse AJDT。
- spring-context.jar:为Spring 核心提供了大量扩展。
- spring-context-support.jar:包含支持UI模版(Velocity,FreeMarker,JasperReports),邮件服务,脚本服务(JRuby),缓存Cache(EHCache),任务计划Scheduling(uartz)方面的类。外部依赖spring-context
- spring-jdbc.jar:包含对Spring 对JDBC 数据访问进行封装的所有类。
- spring-test.jar:spring整合JUnit测试的类。
- spring-web.jar:包含Web 应用开发时,用到Spring 框架时所需的核心类,包括自动载入Web Application Context 特性的类、Struts 与JSF 集成类、文件上传的支持类、Filter 类和大量工具辅助类。外部依赖spring-context, Servlet API, (JSP API, JSTL, Commons FileUpload, COS)。
- spring-webmvc.jar:包含Spring MVC 框架相关的所有类。包括框架的Servlet,Web MVC框架,控制器和视图支持。当然,如果你的应用使用了独立的MVC 框架,则无需这个JAR 文件里的任何类。外部依赖spring-web。
- spring-jms.jar:提供对JMS 1.0.2/1.1的支持类。外部依赖spring-beans,spring-dao,JMS API
详解:
https://blog.csdn.net/miao1475458272/article/details/61619228
2.srpingMVC的原理架构
5个组件:DispatcherServlet、HandlerMapping、HandlerAdapter、ViewResolver、View。
详解:
https://my.oschina.net/u/3943244/blog/2250217
3.springMVC注解的意思
@Controller、@Resource和@Autowired、@RequestMapping、
@ModelAttribute和@SessionAttributes、@PathVariable和@RequestParam、
@ResponseBody和@RequestBody、
详解:
https://www.cnblogs.com/leskang/p/5445698.html
PathVariable和RequestParam区别
RequestBody和ResponseBody的使用
4.spring中BeanFactory和ApplicationContext的联系和区别
https://youyu4.iteye.com/blog/2346183
https://blog.csdn.net/zh521zh/article/details/77884897
5.spring的DI(依赖注入)的几种方式
IOC:控制反转,把创建对象交给Spring进行配置
DI:依赖注入,向类里面的属性中设置值。
二者关系:DI不能单独存在,要在Ioc基础之上来完成操作,即要先创建对象才能注入属性值。
注入属性的方式:
set注入、构造方法注入、注解注入、复杂类型注入。还有一些不常用的:p名称空间注入,spel注入。
6.springIOC和AOP的原理
https://blog.csdn.net/u012813201/article/details/77074795
7.spring如何实现事务管理的
事务介绍
Spring并不直接管理事务,而是提供了多种事务管理器,spring将事务管理的职责委托给Hibernate或者mybatis等持久层框架来实现。
Spring事务管理器的接口是org.springframework.transaction.PlatformTransactionManager,通过这个接口,Spring为各个平台如JDBC、Hibernate等都提供了对应的事务管理器,但是具体的实现就是各个平台自己的事情了。
8.spring中循环注入的方式
https://blog.csdn.net/u010644448/article/details/59108799
9.Spring的beanFactory和factoryBean的区别
https://www.jianshu.com/p/05c909c9beb0