对于害怕面试的大三或者大四的小伙伴们,我以我当时找实习工作的情况来做一个大概的知识回顾。
这篇博客大致讲述了Java程序员在找第一份工作时的面试范围,找到心仪工作的小伙伴就当是复习一下Java知识吧!建议收藏哦!!!
先来自我介绍一下吧!
一般问的第一个问题就是,面试官让你自我介绍一下,这个可以根据下面模板来说:
我是来自XX大学 XX学院的 XX,我在大学期间参加过XX比赛,获得过XX奖,爱好是XXX(尽量往编程技术这一块靠)
Java面试宝典
JavaSE基础部分
1、== 和 equals 的区别
- 基本数据类型:用 == 判断是否相等;
- 引用数据类型:==
比较的是内存地址是否一样,不同对象的内存地址不一样,equals比较的是具体的内容,也可以让开发者去定义什么条件去判断两个对象是否一样
2、重写与重载
- 重写Override:表示子类中的方法可以与父类中的某个方法的名称和参数完全相同
- 重载Overload:表示同一个类中可以有多个名称相同的方法,但这些方法的参数列表各不相同,参数个数或类型不同
3、String str = new String(“erpao”); 创建了几个对象?【一个或两个】
- 创建一个对象:常量池存在,则直接new一个对象;
- 创建两个对象:常量池不存在,则在常量池创建一个对象,也在堆里面创建一个对象
4、下面是比较什么? 输出结果是什么? 为什么是这样的结果?
String str1 = new String("erpao");
String str2 = "erpao";
String str3 = "erpao";
System.out.println(str1 == str2); //false
System.out.println(str2 == str3); //true
· · · 比较引用的内存地址是否一样
· · · 第一个是false: new 创建新的对象会开辟新的空间,所以地址不一样
· · · 第二个是true:都是从常量池里面获取,“erpao” 存在于常量池中
5、写出下面代码的各个结果?如果需要两个都为true,应该怎么修改
String s1 = "erpao";
String s2 = s1 + ".net"; //变量 + 常量 = 来自堆
String s3 = "erpao" + ".net"; //常量 + 常量
System.out.println(s2 == "erpao.net"); //false
System.out.println(s3 == "erpao.net"); //true
· · · 如果需要第一个输出为true,只需要把变量改为常量即可 fianl String s1 = “erpao”;
1. 多线程(重要)
多线程是非常重要的,好多面试官第一个问到的技术问题就是多线程问题!
实现多线程的几种方法:(前面两种必须回答上来)
- 继承Thread类
- 实现Runnable接口
- 使用匿名内部类的形式
- 使用Lambda表达式
- 使用Callable和Future创建线程
- 使用线程池 例如用Exector框架
- Spring的 @Async异步注解 结合线程池
2. 集合(重要)
List
Vector和ArrayList、LinkedList联系和区别?分别的使用场景:
-
线程安全
·· ArrayList:底层是数组实现,线程不安全,查询和修改非常快,但是增加和删除慢
·· LinkedList: 底层是双向链表,线程不安全,查询和修改速度慢,但是增加和删除速度快
·· Vector: 底层是数组实现,线程安全的,操作的时候使用synchronized进行加锁 -
使用场景
·· 查询和修改多则用ArrayList
·· 增加和删除场景多则用LinkedList
·· Vector已经很少用了
ArrayList的扩容机制
- 注意:JDK1.7之前ArrayList默认大小是10,JDk1.7之后是0
- 未指定集合容量,默认是0,若已经指定大小则集合大小为指定的; 【指定大小为100:List list = new ArrayList<>(100);】
- 当集合第一次添加元素的时候,集合大小扩容为10
- ArrayList的元素个数大于其容量,扩容后的大小 = 原始大小 + 原始大小/2 【10 -> 15】
如果需要保证线程安全,ArrayList应该怎么做,用有几种方式
· · · 方式一:自己写个包装类,根据业务一般是add/update/remove加锁
· · · 方式二:Collections.synchronizedList(new ArrayList<>()); 使用synchronized加锁
· · · 方式三:CopyOnWriteArrayList<>() 使用ReentrantLock加锁
了解CopyOnWriteArrayList吗?和 Collections.synchronizedList实现线程安全有什么区别, 使用场景是怎样的?
-
CopyOnWriteArrayList:
执行修改操作时,会拷贝一份新的数组进行操作(add、set、remove等),代价十分昂贵,在执行完修改后将原来集合指向新的集合来完成修改操作, 源码里面用ReentrantLock可重入锁来保证不会有多个线程同时拷贝一份数组。
使用场景: 读高性能,适用读操作远远大于写操作的场景中使用(读的时候是不需要加锁的,直接获取,删除和增加是需要加锁的,读多写少) -
Collections.synchronizedList:
线程安全的原因是因为它几乎在每个方法中都使用了synchronized同步锁
使用场景: 写操作性能比CopyOnWriteArrayList好,读操作性能并不如CopyOnWriteArrayList
CopyOnWriteArrayList的设计思想是怎样的,有什么缺点?
- 设计思想:读写分离+最终一致
- 缺点:内存占用问题,写时复制机制,内存里会同时驻扎两个对象的内存,旧的对象和新写入的对象, *如果对象大则容易发生Yong GC和Full GC。
set: 无序,不允许存在重复的元素
list: 有序,可以存在重复元素
set 和 list 对比: 都是Collection的子接口,Collection是集合类;
set 检查元素效率低下,删除和插入的效率高,插入和删除不会引起元素的位置变化;
list 和数组类似,List可以动态增长,查找元素的效率较高,插入元素和删除元素效率低,因为会引起其他元素位置发生变化
map: Map接口不是Collection接口的继承,而是从自己的用于维护键值对关联的接口层次结构入手,按定义,该接口描述了从不重复的键到值的映射
3. 接口与抽象类(重要)
接口
- 接口使用interface修饰;
- 接口不能实例化;
- 类可以实现多个接口;
- ①java8之前,接口中的方法都是抽象方法,省略了public abstract。
②java8之后;接口中可以定义静态方法,静态方法必须有方法体,普通方法没有方法体,需要被实现;
抽象类 【在class前面加上abstract就是一个抽象类】
- 抽象类使用abstract修饰;
- 抽象类不能被实例化;
- 抽象类只能单继承;
- 抽象类中可以包含抽象方法和非抽象方法,非抽象方法需要有方法体;
- 如果一个类继承了抽象类,
①如果实现了所有的抽象方法,子类可以不是抽象类;
②如果没有实现所有的抽象方法,子类仍然是抽象类。
5. MyBatis 一、二级缓存(重要)
- 查询顺序:优先查询二级缓存 -> 查询一级缓存 -> 数据库
- MyBatis是默认开启一级缓存的,二级缓存要手动开启;
- 一级缓存的作用域是SQLSession;二级缓存是在多个SqlSession在同一个Mapper文件中共享的缓存,它是Mapper级别的,作用域是Mapper文件中的namespace;
- 一级缓存失效策略:当执行SQL的时候,两次查询中间发生了增删改的操作,commit后会清空该SQLSession缓存。比如SQLSession关闭,或者清空等。
- 二级缓存失效策略:执行同个namespace下的mapper映射文件中增删改SQL,并执行了commit操作,会清空该二级缓存
- 实现二级缓存的时候,MyBatis建议返回的POJO是可序列化的,也就是建议实现Serializable接口
面试官:请问你有什么要问的吗?
当面试官问到这个的时候,那就说明他的问题已经问完了。那么你可以问面试官:公司用的是什么技术栈?是不是外包公司?需不需要驻场?公司薪资待遇如何 等等······
当然,作为实习生,最重要的还是要问一下公司现在用的是什么技术栈。如果用的还是jsp,Struts等这些很老的技术栈,那你就需要谨慎考虑了。因为如果你用这些巨老的技术栈工作一两年,再跳槽 出去找工作那将是很难的。