自己 java 面试的一些总结
java 基础
-
== 与 equals 的区别
== 直接比较栈内存引用的数据,对于基础数据类型栈内存直接引用的就是值,所以可以直接使用。常量字符串由于保存在字符串常量池,所以可以常量字符串直接比较也会返回
true。 equals 定义在 Object对象里面,Object 源码里面 equals 方法调用的就是 ==。所有包装类都有对 equals 方法的覆盖。
自己定义的类需要覆盖equals 方法,必须要覆盖
hashCode方法以下内容摘自<> 覆盖equals时总要覆盖hashCode,一个很常见的错误根源在没有覆盖hashCode方法。在每个覆盖了equals方法的类中,也必须覆盖hashCode方法。如果不这样做的话,就会违反Object.hashCode的通用约定,从而导致该类无法结合所有基于散列的集合一起正常工作,这样的集合包括HashMap、HashSet和Hashtable。
同时equals 需要满足下面几条定义:
- 自反性。对于任何非null的引用值x,x.equals(x)必须返回true
- 对称性。对于任何非null的引用值x和y,当且仅当y.equals(x)返回true时,x.equals(y)必须返回true。
- 传递性。对于任何非null的引用值x、y和z,如果x.equals(y)返回true,并且y.equals(z)返回true,那么x.equals(z)则必须返回true。
- 一致性。对于任何非null的引用值x、y,只要equals的比较操作在对象中所用的信息没有被修改,多次调用x.equals(y)就会一直返回true,或者一致返回false。
- 对于任何非null的引用值x,x.equals(null)必须返回false。
-
说下 String, StringBuffer和StringBuilder
String 为了安全性和效率问题所以设计成了
final,所以在没有StringBuffer 和 StringBuilder 的情况下。字符串的每次拼接都会生成多个对象还要将字符串推到字符常量池。String更多细节点击 为了解决字符串拼接的效率问题,推出了
StringBuffer。StringBuffer 是一个线程安全类。可能是因为StringBuffer 底层是字符数组,考虑到数组扩容的情况会导致脏数据。所以采用线程安全的方式。但是StringBuffer 基本没有用到的场景,在多线程还是单线程的情况下都是用 StringBuilder,因为在多线程的情况下我们需要自己控制线程流程,而且StringBuffer 也只是保证append等操作是线程安全的,多线程情况下也保证不了数据的完整性 1.5 之后java 就推出了
StringBuilder是一个线程不安全的类 , StringBuilder 和 buffer 的区别就是方法上没有加synchronized关键字。StringBuilder 出现之后,String str = "Hello, " + "World";这种代码编译的时候都会替换成用StringBuilder拼接。 -
多线程
主要说出四个类:Runnable(1.8 之后是变成函数式接口了),Thread,Callable(1.8 之后是变成函数式接口了),FutureTask
Runnable:只是一个标识性的接口,里面有个run方法Thread:构造函数负责接收Runnable的,start()方法通过JNI调用不同系统的底层生成一个线程,并让线程处于就绪状态。由CPU线程的什么时候运行什么时候切换。Callable:和 Runnable 差不多的一个接口,只是带有返回值。FutureTask:间接继承 Runnable,两个构造函数,一个可以接收 Runnable和一个固定值,一个接收Callable。执行也是传递给Thread 然后执行start 方法。FutureTask 还有一些API 方法可自行查阅。
-
线程池
手动写线程会造成浪费,所以实际编程中我们都是使用线程池来操作线程。
用
ExecutorService来接收Executors线程工厂里面的不同线程池策略,线程池里面又包含很多参数可以设置。详情参阅这里 Spring 框架还有对线程池的进一步的封装。
-
IO
IO 主要分类两大类:
字节流(对 byte 进行操作)和字符流(对 char 进行操作)。两者的根本区别在于字符流有个缓冲区对字节进行处理。 常用的有:
buffer:使用了缓存区操作,提高效率
Piped:管道流,多线程的情况下使用的
IO 牵扯的东西太多了,能力有限不多写了,除去传统的
BIO还有NIO和AIO。具体的大家多看看别人具体对IO 写的文章吧
Spring 框架系列
-
Spring 的IOC
Spring 实现IOC 的方式是通过DI(依赖注入),通过配置的方式将bean 保存到Spring 的容器(BeanFactory)。当我们需要某个类的时候都是通过Spring 去获取。
-
Spring 的AOP
AOP 是通过动态代理来实现的,Spring 有两种动态代理的方式(JDK自带的和CGLIB),动态代理主要应用到了反射机制。主要应用在日志和事务上面。
-
SpringMVC
MQ 和Redis
掘金里面已经有很多对redis 写的很好的文章了。
MQ 推荐这一篇:90%的Java程序员,都扛不住这波消息中间件的面试四连炮!
还有很多内容没有写到,首先因为自己也没有理解透彻,再次已经有了很好的文章了就不在这里东施效颦了