写在前面
对于 Java 基础的部分常见的面试问题,进行整理。
1. Java 抽象类 和 接口的区别
整体来说,接口 就是 极度抽象的 抽象类。
二者区别在于:
- 接口只有方法的定义,所有方法都是抽象方法;而抽象类中有抽象方法,也有已经实现了的方法。
由于二者都有没有实现的方法,所以都是不能直接用来初始化实例的。
-
成员变量:接口中成员变量只能是 static final,并且要初始化,其实现类无法更改。 抽象接口中成员类没有要求
-
类可以实现多个接口,只能继承一个类
-
应用场景:接口关注于动作,抽象类关注于本质
比如说你现在定义一个 Animal 基类,那就是要用 抽象类。。类里面可能含有 name() 方法,这个是共用的,所以不应该是抽象方法;可能还含有 legs() 方法,那就应该是抽象的,具体动物具体去实现。
但是如果定义一个 Action 接口,用来描述动物的动作,那就用接口。
2. Java8 的新特性
这里我们说三个,不只要说出来,还要大概明白应用是怎样的。
- Lambda 表达式
这里写一个应用
public void test(){
// 匿名内部类
Runnable runnable = new Runnable(){
@override
public void run(){
sout("线程启动了");
};
}
// lambda
Runnable runnable = ()->sout("线程启动了");
}
- 接口的 default 方法 和 static 方法
default 方法,包含方法的实现。个人理解这里有点像抽象类了
public static 方法,可以直接不用实例化就能调用, interface.staticMethod()。
- 链表长度超过8,转成红黑树
这里可以用 HashMap 的底层数据结构来说明。当链表长度过长后,变成红黑树,查找的时间复杂度从 O(n)--> logn
3. 重写 equals() 方法 和 hashCode()
重写 equals() 方法没什么说的,大概就是
- 先判断是不是同一性
- 在判断相等性
euqals(Object obj){
if(this==obj) return true; // 同一个引用当然是相等满足同一性,也满足相等性
if(obj instanceof XXX){
UserOverrideEquals other = (UserOverrideEquals) obj;
if(this.name.equals(other.name)&&
this.age.equals(other.age))
return true;
}
return false;
}
}
这里的 equals() 方法写完了,还要重写 hashCode() 方法,因为按照规定是要有 相同对象的hashCode 必须相同
重写 hashCode 方法大概就是
- 设定一个hash初始值 int result
- 对每一个关键字,执行 result = 31 * result + (keyValue==null? 0 : super.hashCode(obj))
public int hashCode() {
int result = 17;
result = 31*result+(name==null?0:name.hashCode());
result = 31*result+(age==null?0:name.hashCode());
return result;
}
为什么是31,因为太小会造成算出来 hash 范围不大,hash冲突;太大会造成超过 intMax,同时 31 可以被JVM优化。
4. Stirng Buffer 和 String Builder 和 String 的区别
- StringBuffer 和 String Builder 中的方法和功能是完全等价的
- StringBuffer 中的方法,大多都采用了 Syn 来做同步,是线程安全的。StringBuilder 是线程不安全的
- 基于2点,StringBuilder 在单线程上更快,没有锁的消耗
String 字符串常量
StringBuffer 字符串变量(线程安全)
StringBuilder 字符串变量(非线程安全)
总结来说,
String 适用于少量字符串操作的情况
StringBuffer 适用于大量字符串操作,多线程
StringBuilder 适用于大量字符串操作,单线程
5. Java 中的 OOM(OutOfMemory)
之前讲到 JVM 的时候,在面试中常常会问, OOM 这个问题有没有遇到过,怎么解决的。
1. 为什么 OOM / 什么情况下 OOM
两个原因:
- 分配的内存少了:JVM本身可用的内存少了
- 使用的内存多了:使用的对象太多了,用完没有GC
2. OOM的类型
这里其实除了 程序计数器不会抛出 OOM 之外,其他的内存区都会OOM。这里我们只看一下常见3种OOM
- Stack Overflow
栈溢出问题比较简单,如果递归调用,返回条件没有写好,反复栈帧入栈,就会报错 stack overflow
出现这个问题后,可以通过 -Xss(stack space) 参数来增加栈的大小 - java.lang.OutOfMemoryError: Java heap space 堆内存溢出
-原因:就是堆内存不够了。
- 分析:可以使用 jdk 工具, jmap -dump 将java 进程的内存 dump 成一个快照文件,再使用相关的工具 IBM Heap Analyzer 分析这个文件
- 解决: -Xms(memory space)参数将堆大小增大
- java.lang.OutOfMemoryError: Java PermGen space 永久代(方法区)溢出
- 原因:出现大量的 Classs、出现过多的字符串常量
- 分析:
- 解决: -XX:PermSize 调整方法区大小
网友评论