Tips
面试指南系列,很多情况下不会去深挖细节,是小六六以被面试者的角色去回顾知识的一种方式,所以我默认大部分的东西,作为面试官的你,肯定是懂的。
上面的是脑图地址
叨絮
可能大家觉得有点老生常谈了,确实也是。面试题,面试宝典,随便一搜,根本看不完,也看不过来,那我写这个的意义又何在呢?其实嘛我写这个的有以下的目的
- 第一就是通过一个体系的复习,让自己前面的写的文章再重新的过一遍,总结升华嘛
- 第二就是通过写文章帮助大家建立一个复习体系,我会将大部分会问的的知识点以点带面的形式给大家做一个导论
然后下面是前面的文章汇总
最后就是以面试题的形式来回顾所有的知识点,会整理一些比较常见的面试题和自己实际开发碰到的问题等题目。
Java基本功
Java字符型常量和字符串常量的区别?
我们在开发的过程中,用的比较多的应该是字符串,所以要熟悉下字符常量,我们可以回答
- 形式上: 字符常量是单引号引起的一个字符; 字符串常量是双引号引起的 0 个或若干个字符
- 含义上: 字符常量相当于一个整型值( ASCII 值),可以参加表达式运算; 字符串常量代表一个地址值(该字符串在内存中存放位置)
- 占内存大小 字符常量只占 2 个字节; 字符串常量占若干个字节
String和StringBuilder、StringBuffer的区别?
- Java 平台提供了两种类型的字符串:String 和 StringBuffer/StringBuilder,它们可以储存和操作字符串。
- 其中 String 是只读字符串,也就意味着 String 引用的字符串内容是不能被改变的。
- 而 StringBuffer/StringBuilder 类表示的字符串对象可以直接进行修改。StringBuilder 是 Java 5 中引入的,它和 StringBuffer 的方法完全相同,区别在于它是在单线程环境下使用的,因为它的所有方面都没有被 synchronized 修饰,因此它的效率也比 StringBuffer 要高。
小六六多嘴下,其实也是在告诫自己,其实我相信这个题目的答案大部分的人都是会的,也背的滚瓜烂熟,但是我们真正在开发的过程中确是没有遵守的,比如有时候我们处理一些逻辑的时候,需要拼接些字段的时候我们会习惯的用+,不知道有没有同款开发。哈哈,小六六和大家一起尽量养成好的开发习惯哈
说说反射的用途及实现
Java 反射机制是一个非常强大的功能,在很多的项目比如 Spring,MyBatis 都都可以看到反射的身影。通过反射机制,我们可以在运行期间获取对象的类型信息。利用这一点我们可以实现工厂模式和代理模式等设计模式,同时也可以解决 Java 泛型擦除等令人苦恼的问题。
获取一个对象对应的反射类,在 Java 中有下列方法可以获取一个对象的反射类
- new 一个对象,然后对象.getClass()方法
- 通过 Class.forName() 方法
- 使用 类.class
说说有没有碰到BigDecimal的坑,或者说需要注意的点
- 我们在使用BigDecimal时,为了防止精度丢失,推荐使用它的 BigDecimal(String) 构造方法来创建对象。
其实就是想知道我们的实际开发是否有注意到这些点,
说说你平时是怎么把一个逗号隔开的字符串变成一个集合的,类似于("1,2,3")这种
- List myList = Arrays.stream(myArray).collect(Collectors.toList()),建议使用这种方式,而不是List myList = Arrays.asList(1, 2, 3);
- 至于原因就是Arrays.asList()将数组转换为集合后,底层其实还是数组
说说String s="abc"和String s=new String("abc")区别;
- 相信大家对这道题并不陌生,答案也是众所周知的,1个或2个。
- 首先在堆中(不是常量池)创建一个指定的对象"abc",并让str引用指向该对象
- 在字符串常量池中查看,是否存在内容为"abc"字符串对象
- 若存在,则将new出来的字符串对象与字符串常量池中的对象联系起来
- 若不存在,则在字符串常量池中创建一个内容为"abc"的字符串对象,并将堆中的对象与之联系起来
聊聊Java中的SPI
系统设计的各个抽象,往往有很多不同的实现方案,在面向的对象的设计里,一般推荐模块之间基于接口编程,模块之间不对实现类进行硬编码。一旦代码里涉及具体的实现类,就违反了可拔插的原则,如果需要替换一种实现,就需要修改代码。为了实现在模块装配的时候能不在程序里动态指明,这就需要一种服务发现机制。 Java SPI就是提供这样的一个机制:为某个接口寻找服务实现的机制。有点类似IOC的思想,就是将装配的控制权移到程序之外,在模块化设计中这个机制尤其重要。所以SPI的核心思想就是解耦。
聊聊Java 8有哪些特性
- 函数式接口
- 接口可以有实现方法,而且不需要实现类去实现其方法。
- lambda表达式
- stream流
- 日期时间 API LocalDateTime年月日十分秒;LocalDate日期;LocalTime时间
- Optional 类
虽然说目前最新的版本已经是15了,但是大部分企业还是用的8,所以就聊聊这个拉。
说说成员变量与局部变量的区别有哪些?
- 成员变量可以被 public,private,static 等修饰符所修饰,而局部变量不能被访问控制修饰符及 static 所修饰;但是,成员变量和局部变量都能被 final 所修饰。
- 从变量在内存中的存储方式来看:如果成员变量是使用static修饰的,那么这个成员变量是属于类的,如果没有使用static修饰,这个成员变量是属于实例的。而对象存在于堆内存,局部变量则存在于栈内存
- 从变量在内存中的生存时间上看:成员变量是对象的一部分,它随着对象的创建而存在,而局部变量随着方法的调用而自动消失。
- 成员变量如果没有被赋初值:则会自动以类型的默认值而赋值(一种情况例外:被 final 修饰的成员变量也必须显式地赋值),而局部变量则不会自动赋值。
说说构造方法有哪些特性?
- 名字与类名相同。
- 没有返回值,但不能用 void 声明构造函数。
- 生成类的对象时自动执行,无需调用。
说说==和equals
- == : 它的作用是判断两个对象的地址是不是相等。即,判断两个对象是不是同一个对象(基本数据类型==比较的是值,引用数据类型==比较的是内存地址)。
- equals() : 它的作用也是判断两个对象是否相等。但它一般有两种使用情况:
- 情况 1:类没有覆盖 equals() 方法。则通过 equals() 比较该类的两个对象时,等价于通过“==”比较这两个对象。
- 情况 2:类覆盖了 equals() 方法。一般,我们都覆盖 equals() 方法来比较两个对象的内容是否相等;若它们的内容相等,则返回 true (即,认为这两个对象相等)。
聊聊Java的四种引用,强弱软虚
小六六这边说下,其实我们作为一个crud仔,平时真正接触到的也许就是强引用了,但是也不是说其他的引用方式没有用,存在即合理,我们来看看他们具体的作用吧!感觉应该放到JVM模块的,算了,就这个吧
- 强引用:最普遍的一种引用方式,如String s = "abc",变量s就是字符串“abc”的强引用,只要强引用存在,则垃圾回收器就不会回收这个对象。
- 软引用:用于描述还有用但非必须的对象,如果内存足够,不回收,如果内存不足,则回收。一般用于实现内存敏感的高速缓存(自定义内存cached的时候用),软引用可以和引用队列ReferenceQueue联合使用,如果软引用的对象被垃圾回收,JVM就会把这个软引用加入到与之关联的引用队列中。
- 弱引用:弱引用和软引用大致相同,弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。(这个就比较垃圾了)
- 虚引用:虚引用不会改变对象的生命周期,如果一个对象仅持有虚引用,那么它就和没有任何引用一样。(其实小六六自己对于虚引用的理解还是因为ThreadLocal,防止我们忘记remove)
Java容器集合
聊聊数组的特点呗
- 一致性:数组只能保存相同数据类型元素,元素的数据类型可以是任何相同的数据类型。
- 有序性:数组中的元素是有序的,通过下标访问。
- 不可变性:数组一旦初始化,则长度(数组中元素的个数)不可变。 数组是一种连续存储线性结构,元素类型相同,大小相等
说说Java常见的集合有哪些
嗯,我觉得这题会经常问,算是一个对集合考查的引入吧
- Map接口和Collection接口是所有集合框架的父接口
- Collection接口的子接口包括:Set接口和List接口
- Map接口的实现类主要有:HashMap、TreeMap、Hashtable、ConcurrentHashMap以及Properties等
- Set接口的实现类主要有:HashSet、TreeSet、LinkedHashSet等
- List接口的实现类主要有:ArrayList、LinkedList、Stack以及Vector等
简单聊聊 Set、List、Map的区别
List
- 可以允许重复的对象。
- 可以插入多个null元素。
- 是一个有序容器,保持了每个元素的插入顺序,输出的顺序就是插入的顺序。
Set
- 不允许重复对象
- 无序容器,你无法保证每个元素的存储顺序,TreeSet通过 Comparator 或者 Comparable 维护了一个排序顺序。
- 只允许一个 null 元素
Map
- Map不是collection的子接口或者实现类。Map是一个接口。
- Map 的 每个 Entry 都持有两个对象,也就是一个键一个值,Map 可能会持有相同的值对象但键对象必须是唯一的。
- Map 里你可以拥有随意个 null 值但最多只能有一个 null 键。
他们的使用场景
- 如果你经常会使用索引来对容器中的元素进行访问,那么 List 是你的正确的选择。如果你已经知道索引了的话,那么 List 的实现类比如 ArrayList 可以提供更快速的访问,如果经常添加删除元素的,那么肯定要选择LinkedList。
- 如果你想容器中的元素能够按照它们插入的次序进行有序存储,那么还是 List,因为 List 是一个有序容器,它按照插入顺序进行存储。
- 如果你想保证插入元素的唯一性,也就是你不想有重复值的出现,那么可以选择一个 Set 的实现类,比如 HashSet、LinkedHashSet 或者 TreeSet。所有 Set 的实现类都遵循了统一约束比如唯一性,而且还提供了额外的特性比如 TreeSet 还是一个 SortedSet,所有存储于 TreeSet 中的元素可以使用 Java 里的 Comparator 或者 Comparable 进行排序。LinkedHashSet 也按照元素的插入顺序对它们进行存储。
- 如果你以键和值的形式进行数据存储那么 Map 是你正确的选择。你可以根据你的后续需要从 Hashtable、HashMap、TreeMap 中进行选择。