1.对比Exception和Error,运行时异常和一般异常有什么不同?
Exception和Error都继承了Throwable类,只有Throwable类的实例才可以被抛出(throw)或者捕获(catch),它是异常处理机制的基本类型。
Exception是程序可以预料的意外情况,应该被捕获并进行处理;Error是会导致程序处于非正常、不可恢复的状态的情况,不便于也不需要捕获。
Exception又可分为可检查异常和不检查异常。
可检查异常是编译阶段检查的一部分,必须显式进行捕获处理;不检查异常也称运行时异常,通常是可以避免的逻辑错误,根据需要判断是否需要捕获,不强制要求。
Exception:
- 检查异常:IOException、SQLException
- 运行时异常:NullPointerException、ClassCastException、SecurityException
Error:
- LinkageError:NoClassDefFoundError、UnsatisfiedLinkError、ExceptionInitializerError
- VirtualMachineError:OutOfMemoryError、StackOverflowError
2.谈谈Java反射机制,动态代理基于什么原理
反射机制是Java语言提供的一种基础功能,通过反射可以直接操作 类 或者 对象,比如获取某个对象的类定义,获取类声明的属性和方法,调用方法或者构造对象,甚至可以在运行时修改类定义。
动态代理是一种方便运行时 动态构建代理、动态处理代理方法 调用的机制。很多场景利用类似机制做到,如包装RPC调用、面向切面编程(AOP)。
实现动态代理的方法有很多,如JDK自身提供了动态代理,就是利用反射机制。其他还有利用性能更高的字节码操作机制,如ASM、cglib(基于ASM)、Javassist等。
3.谈谈抽象类和接口有什么区别?
- 继承抽象类的子类之间本质是相似的,体现一种“is-a”的关系,比如猫和狗都是动物;对于接口的继承更多是一种行为的相似,体现一种“like-a”的关系,比如飞机和鸟,都具有飞的行为,但不需要本质的相似。
- 抽象类可以拥有任意范围的成员数据,可以抽象,也可非抽象;接口中所有方法必须抽象,成员变量必须是public static final。某种程度上,接口是抽象类的一种抽象。
- 一个类只能继承一个抽象类,却可以实现多个接口。
4.synchronized和ReentrantLock有什么区别,说synchronized最慢是否靠谱?
synchronized是Java内建的同步机制,提供了互斥的语义和可见性,当一个线程已经获取当前锁,其他试图获取的线程只能等待或者阻塞在那里。
在Java 5 之前,synchronized是仅有的同步手段,它可以修饰方法,也可以使用的特定的代码块上。
ReentrantLock通常译为再入锁,是Java 5提供的锁实现,语义和synchronized基本相同。它通过调用lock()方法获取,代码书写更灵活,更提供了很多实用方法,实现很多synchronized无法做到的细节控制,如控制fairness,也就是公平性,或者定义条件等。但需要注意的是,必须明确调用unlock()方法释放,否则会一直持有该锁。
早期版本的synchronized在很多场景性能相差较大,后续版本其实已经做了很多改进,在低竞争的场景中表现可能优于ReentrantLock。