java面试总结
基础部分:
JAVA中的几种基本类型,各占用多少字节?
String能被继承吗?为什么?
不能被继承,因为String类有final修饰符,而final修饰的类是不能被继承的。
Java接口与抽象类的区别:
相同点:
都位于继承的顶端,用于被其他类实现或继承; 都不能直接实例化对象;
都可能包含抽象方法,其子类都必须重写这些抽象方法; 区别:
1.抽象类为部分方法提供实现,避免子类重复实现这些方法,提高代码重用性;接口只能包含抽象方法;
2.一个类只能继承一个直接父类(可能是抽象类),却可以实现多个接口;(接口弥补了Java的单继承)
3.抽象类是这个事物中应该具备的内容, 继承体系是一种 is..a关系 4.接口是这个事物中的额外内容,继承体系是一种 like..a关系 二者的选用:
优先选用接口,尽量少用抽象类;
需要定义子类的行为,又要为子类提供共性功能时才选用抽象类;
集合
ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。
HashMap采用数组+链表+红黑树实现(当链表长度超过阈值(8)时,将链表转换为红黑树,这样大大减少了查找时间。)。
ArrayList:初始容量为10,加载因子1,扩容到1.5倍 (15)
linkedList 是一个双向链表,没有初始化大小,也没有扩容的机制。 Vector:10,1,2 (20)
HashSet:16,0.75,2 (32) HashMap:16,0.75,2 (32)
Hashtable:11,0.75,1倍+1 (23)
HashMap和Hashtable的区别:
1、线程安全
两者最主要的区别在于Hashtable是线程安全,而HashMap则非线程安全。Hashtable的实现方法里面都添加了synchronized关键字来确保线程同步,因此相对而言HashMap性能会高一些。
2、针对null的不同
HashMap可以使用null作为key,而Hashtable则不允许null作为key。 3、初始容量与扩容
HashMap的初始容量为16,Hashtable初始容量为11,两者的填充因子默认都是0.75。HashMap扩容时是当前容量翻倍即:capacity*2,Hashtable扩容时是容量翻倍+1即:capacity*2+1。
HashMap的实现原理:
1.利用key的hashCode计算出当前对象的元素在数组中的下标
2.存储时,如果出现与表相同的key,放入链表中,当链表数量到达8的时候链表就变成红黑树。
equals和==:
1)对于==,如果作用于基本数据类型的变量,则直接比较其存储的 “值”是否相等;如果作用于引用类型的变量,则比较的是所指向的对象的地址
2)对于equals方法,注意:equals方法不能作用于基本数据类型的变量
如果没有对equals方法进行重写,则比较的是引用类型的变量所指向的对象的地址;诸如String、Date等类对equals方法进行了重写的话,比较的是所指向的对象的内容。
多线程
创建线程的几种方式:
1.继承Thread类 2.实现Runnable接口
3.实现Callable接口((1)call方法可以有返回值(2)call方法可以声明抛出异常) 4.使用线程池框架
线程的5种状态:
新建、就绪、运行、阻塞、死亡
线程同步的方法:
1.同步方法(有synchronized关键字修饰的方法)
2.同步代码块(有synchronized关键字修饰的语句块) 3.使用特殊域变量(volatile)实现线程同步(加在变量上) 4.使用重入锁实现线程同步(ReentrantLock)
常用的线程池有哪些?
newSingleThreadExecutor:创建一个单线程的线程池,此线程池保证所有任务的执行顺序按照任务的提交顺序执行。
newFixedThreadPool:创建固定大小的线程池,每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小。
newCachedThreadPool:创建一个可缓存的线程池,此线程池不会对线程池大小做限制,线程池大小完全依赖于操作系统(或者说 JVM)能够创建的最大线程大小。
newScheduledThreadPool:创建一个大小无限的线程池,此线程池支持定时以及周期性执行任务的需求。
volatile和synchronized的区别:
1.volatile仅能使用在变量级别;synchronized则可以使用在变量、方法、和类级别的
2.volatile本质是在告诉jvm当前变量在缓存中的值是不确定的,需要从主存中读取;synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住。
什么是死锁:
线程死锁是指由于两个或者多个线程互相持有对方所需要的资源,并且互相等待对方释放资源,如果线程都不主动释放所占有的资源,将产生死锁。
如何避免死锁:
1.加锁顺序(线程按照一定的顺序加锁)
2.加锁时限(线程尝试获取锁的时候加上一定的时限,超过时限则放弃对该锁的请求,并释放自己占有的锁) 3.死锁检测
反射
定义:
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
Class获得方式:
1.类名.class
2.变量名.getClass()
3.Class.forName(\全限定类名\ 什么是Java序列化:
序列化:把Java对象转换为字节序列的过程。
静态代理:
若代理类在程序运行前就已经存在,那么这种代理方式被成为 静态代理 ,这种情况下的代理类通常都是我们在Java代码中定义的。
动态代理:
代理类在程序运行时创建的代理方式被成为 动态代理。 也就是说,这种情况下,代理类并不是在Java代码中定义的,而是在运行时根据我们在Java代码中的“指示”动态生成的。相比于静态代理, 动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类的函数。
动态代理,照我的理解就是,在不修改原有类对象方法的源代码基础上,通过代理对象实现原有类对象方法的增强,也就是拓展原有类对象的功能。
Java实现动态代理的两种方式:
Java领域中,常用的动态代理实现方式有两种,一种是利用JDK反射机制生成代理,另外一种是使用CGLIB代理。JDK代理必须要提供接口,而CGLIB则不需要,可以直接代理类。
web
JSP 和 servlet 有什么区别?
JSP 是 servlet 技术的扩展,本质上就是 servlet 的简易方式。JSP 侧重于视图,servlet 主要用于控制逻辑。
jsp的九大内置对象:
名字 request response session out application: pageContext: exception :
本身类 httpServletRequest httpServletResponse httpSession
可以理解为response.getWriter() servletContext PageContext jsp页面域对象
java.lang.ThrowAble