自我介绍
equals与 == 比较以及equals的具体原理
- 对于没有重写Object的equals()方法的类型所生成的对象的比较,equals()和==效果是一样的,==比较的是两个变量所指向的对象在内存中指向的地址是否一样,而当两个变量的类型中继承了object的equals()方法时候,由于该方法比较的标准是看哈希码是否相等,而哈希码是由hashcode()方法生成的,该方法生成哈希码的依据是对象在内存中的地址,最终比较的地址是一样的
- 像String和那些基本数据类型的包装类来说,equals()和==就不一样了,因为他们重写了object的equals方法和hashcode方法,使得equals方法的判断标准发生了改变,他们判断的标准是看对象的内容是否相等,也就是值是不是一样,因为哈希码是根据对象的值生成的,与内存地址无关,所以equals方法比较的是对象的值是否相等,而==比较的是地址,所以equals和==就不一样了
- 比较值的时候,一般==比较的是基本数据类型,而equals比较的是引用数据类型,地址相同一定值相等,而值相等地址不一定相同。如果比较的是地址,最好是用==,equals比较的是哈希码,而哈希码生成的标准是由类作者自己根据需求来控制的。
HashMap的源码,扩容机制
- hashMap不是线程安全的,在扩容的时候hashMap会产生环,造成死循环;hashMap在插入新阶段的时候,多个线程会同时插入,会把除了最后的那个线程的其他线程的结点丢失;对于修改的时候,多个线程修改,对只保留最后一个线程的修改结果;扩容的时候,只保留最后一个线程的扩容后的那个数组
- hashMap的数据结构数组链表结构,hashMap的put方法是向hashMap中添加新的元素,从put方法的具体实现可知,会先调用hashCode方法得到该元素的hashCode值,然后查看table中是否存在该hashCode值,如果存在则调用equals方法重新确定是否存在该元素,如果存在,则更新value值,否则将新的元素添加到HashMap中。从这里可以看出,hashCode方法的存在是为了减少equals方法的调用次数,从而提高程序效率。
抽象类和接口
- 抽象类和接口都不能直接实例化,如果要实例化。抽象类必须要指向所有抽象方法的子类对象,接口变量必须指向所有接口方法的类对象。
- 抽象类要被子类继承而且只能单继承,接口要被类实现还可以实现多个接口
- 抽象类中有一个或者多个抽象方法,接口中的方法必须都为抽象方法
- 抽象类变量可以使用private、public修饰符,接口成员变量默认使用public static final
- 抽象类可以定义构造器,接口不可以定义构造器
- 抽象类中可以有静态方法,接口中不能有静态方法
集合:List、set、vector/map
- ArrayList底层是数组,查找数据快;LinkedList底层是链表,插入和删除快
- LinkedList可以用For循环吗?答案是能不用尽量不用,不推荐,可以用迭代器进行遍历
- List元素存放有序,可重复,支持for循环也可以用迭代器;set元素无放入顺序,不可重复,虽然放入时候无顺序,但其位置是固定的的,是由该元素得Hashcode决定的,Set因为无序,无法用下标来取得值,只能用迭代器。
- Set:检索元素效率低下,删除和插入效率高,插入和删除不会引起元素位置改变。 List:和数组类似,List可以动态增长,查找元素效率高,插入删除元素效率低,因为会引起其他元素位置改变。
- LinkedList、ArrayList、HashSet是非线程安全的,Vector是线程安全的;HashMap是非线程安全的,HashTable是线程安全的;StringBuilder是非线程安全的,StringBuffer是线程安全的。
Hashcode应用在hashMap、concurrentMap
Java内存模型
- JVM运行时数据区包括:程序计数器(Program Counter Register)、Java栈(VM Stack)、本地方法栈(Native Method Stack)、方法区(Method Area)、堆(Heap)
多线程的理解
JVM分为哪几块?内存溢出/内存泄漏
- 方法区,虚拟机栈,本地方法栈,堆,程序计数器,方法区和堆是线程共享的,虚拟机栈本地方法栈和程序计数器是线程私有的,除了程序计数器不会发生内存溢出,其他都会发生内存溢出
- 内存泄漏就是一块申请了一块内存以后,无法去释放掉这块内存,丢失了这段内存的引用
- 内存溢出就是申请的内存不够,撑不起我们需要的内存
GC回收机制,垃圾回收算法
算法有:标记清除,标记整理,复制算法,分代收集
- 标记清除:在标记阶段,确定要回收的对象,并做标记。清除阶段紧随标记阶段,将标记阶段确定不可用的对象清除。标记-清除算法是最基础的收集算法,标记和清除阶段的效率不高,而且清除后会产生大量的不连续空间,这样当程序需要分配大内存对象时,可能无法找到足够的连续空间。
- 复制算法:是把内存分成大小相等的两块,内次使用其中一块,当垃圾回收的时候,把存活的对象复制到另一块上,然后把这块内存整个清理掉。复制算法实现简单,运行效率高,但是由于每次只能使用其中的一半,造成内存的利用率不高,现在的JVM用复制方法收集新生代,由于新生代中大部分对象(99%)都是朝生夕死的,所以两块内存的比例不是1:1(大概是8:1)
- 标记-整理算法:和标记-清除算法一样,但是标记-整理算法不是把存活对象复制到另一块内存,而是把存活对象往内存的一端移动,然后直接回收边界以外的内存。标记-整理算法提高了内存的利用率,并且它适合在收集对象存活时间较长的老年代。
- 分代收集:根据对象的存活时间把内存分为新生代和老年代,根据各个代对象的存活特点,每个代采用不同的垃圾回收算法。新生代采用复制算法,老年代采用标记-整理算法。垃圾算法的实现设计大量的程序细节,而且不同的虚拟机平台实现的方法也各不相同。
单例模式
//饿汉模式
public class Singleton3 {
private static Singleton3 instance=new Singleton3();
private Singleton3(){}
public static Singleton3 getIntance(){
return instance;
}
}
//懒汉模式
public class Singleton2 {
private static Singleton2 instance;
private Singleton2(){}
public static synchronized Singleton2 getIntance(){
if(instance==null){
instance=new Singleton2();
}
return instance;
}
}
//双重校验
public class Singleton4 {
private volatile static Singleton4 instance;
private Singleton4(){}
public static Singleton4 getInstance(){
if(instance==null){
synchronized(Singleton4.class){
if(instance==null){
return instance;
}
}
}
return instance;
}
}
I/O(NIO)
JDBC
SpringMVC的工作原理,springMVC与Struts2的区别
-
1. 用户发送请求至前端控制器DispatcherServlet。
2、 DispatcherServlet收到请求调用HandlerMapping处理器映射器。
3、 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
4、 DispatcherServlet调用HandlerAdapter处理器适配器。
5、 HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。
6、 Controller执行完成返回ModelAndView。
7、 HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。
8、 DispatcherServlet将ModelAndView传给ViewReslover视图解析器。
9、 ViewReslover解析后返回具体View。
10、DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
11、 DispatcherServlet响应用户。
-
SpringMVC其实就是spring在原有基础上,又提供了web应用的MVC模块,可以简单的把springMVC理解为是spring的一个模块(类似AOP,IOC这样的模块)
-
IOC的理解
- IOC(控制反转)利用反射的原理将对象创建的权利交给了spring容器,spring在运行的时候根据配置文件来动态的创建对象和维护对象之间的关系,实现了松耦合的思想
- DI(依赖注入)由Spring容器将对象注入到使用它的地方,被注入的对象只提供对应的方法接收就行,由容器来决定对象之间的依赖关系
- 项目中的Bean都可以交给Spring容器来维护,这样Bean的创建及销毁以及生命周期都由Spring来处理
- DI:比如Service层需要调用Dao层访问数据库,这时可以把Dao层的Bean给Spring管理,我们只需要在Service中定义对应的方法来接收Spring容器负责注入的Dao层的Bean即可
AOP的理解以及对日志、事务的管理实现
SpringMVC中常用注解及作用
@RequestMapping 请求和方法映射
@RequestBody 接收客户端传入的JSON数据
@ResponseBody 返回客户端JSON数据
@Controller 标识控制层
@Repository 标识业务层
@Component 把Bean添加到Spring容器中
@Autowired 按照类型自动注入
@Resource 自定义注入 可以按照类型注入 也可以按照名字注入
@PathVariable RESTful风格时使用
@Param 表单参数和方法形参不一样时使用
Spring的作用域
singleton:默认,每一个Spring都会实例化一个实例对象
prototype:每次调用都会创建一个新的实例
request:每个HTTP请求都由自己的Bean实现,仅基于Web的Spring ApplicationContext中可用
session:每个HTTP请求都会产生一个新的Bean,同时该Bean仅在当前HTTP session内有效
global session:在一个全局的HTTP session中,容器会返回该Bean的同一个实现,仅在使用portletContext时有效
声明式事务和编程式事务
数据的隔离级别
- 未提交读,事务中发生了修改,即使没有提交,其他事务也是可见的。比如一个数A原来是50要修改为100,但是还没提交修改,另一个事务看到这个修改,而这个时候原事务发生了回滚,这时候A还是50,而另一个事务看到的A是100.
- 提交读,一个事务从开始直到提交之前,所做的任何修改是其他事务不可见的,对于一个数A原来是50,然后提交修改成100,由于另一个事务在A提交修改前,读取到了A是50,刚读取完,A就被修改成100了,这时另一个事务再进行读取发现A突然变成了100
- 可重复读,就是对于一个记录读取多次的记录是相同的,就是对于一个数A读取的话一直是A,前后两次读取到的A是一致的,可串行化读,就是说在并发情况下,和串行化读取的结果是一致的,没有什么不同,不会发生脏读和幻读。
数据库优化,数据库四大特性
- 四大特性:原子性,一个事务要么全部完成,要么全部失败,要么做要么不做;一致性,比如a+b=100,一个事务改变了a的值比如增加a的值,那么必须同时改变b,保证事务在结束后a+b=100依然成立;持久性,就是修改完以后,在数据库中生效是永久的;隔离性,对于A对B转账,A每次交易完成的时间,B是不知情的
Mybatis的工作原理
对RestFul的理解
对高并发线程的堵塞以及异常的处理
Redis的数据结构
Executor线程池
JMS的理解
Object的类有哪些?
Clone,getClass,toString,finalize,equals,hashCode,wait,notify,notifyAll
String A=“123”;String B=new String(“123”);生成几个对象?
如果常量池中存在“123”,则生成了1个对象,如果没有就生成了2个对象
Wait和sleep的区别
- Wait和sleep方法都可以使线程进入阻塞状态
- Wait和sleep方法都是可中断方法,被中断后都会收到中断异常
- Wait是Object方法,而sleep方法是Thread特有的方法
- Wait方法的执行必粗在同步方法中进行,而sleep不需要
- 线程在同步方法中执行Wait的话会释放monitor的锁,sleep的话不会释放monitor的锁
Linux的常用命令