美文网首页
Java 基础,常见面试题

Java 基础,常见面试题

作者: MikeShine | 来源:发表于2020-03-01 20:27 被阅读0次

写在前面

对于 Java 基础的部分常见的面试问题,进行整理。


1. Java 抽象类 和 接口的区别

整体来说,接口 就是 极度抽象的 抽象类。
二者区别在于:

  1. 接口只有方法的定义,所有方法都是抽象方法;而抽象类中有抽象方法,也有已经实现了的方法。

由于二者都有没有实现的方法,所以都是不能直接用来初始化实例的。

  1. 成员变量:接口中成员变量只能是 static final,并且要初始化,其实现类无法更改。 抽象接口中成员类没有要求

  2. 类可以实现多个接口,只能继承一个类

  3. 应用场景:接口关注于动作,抽象类关注于本质

比如说你现在定义一个 Animal 基类,那就是要用 抽象类。。类里面可能含有 name() 方法,这个是共用的,所以不应该是抽象方法;可能还含有 legs() 方法,那就应该是抽象的,具体动物具体去实现。
但是如果定义一个 Action 接口,用来描述动物的动作,那就用接口。


2. Java8 的新特性

这里我们说三个,不只要说出来,还要大概明白应用是怎样的。

  1. Lambda 表达式
    这里写一个应用
public void test(){
    //   匿名内部类
    Runnable runnable = new Runnable(){
        @override
        public void run(){
            sout("线程启动了");
        };
    }
    //  lambda
    Runnable runnable = ()->sout("线程启动了");
}
  1. 接口的 default 方法 和 static 方法

default 方法,包含方法的实现。个人理解这里有点像抽象类了
public static 方法,可以直接不用实例化就能调用, interface.staticMethod()。

  1. 链表长度超过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 的区别

一个参考

  1. StringBuffer 和 String Builder 中的方法和功能是完全等价的
  2. StringBuffer 中的方法,大多都采用了 Syn 来做同步,是线程安全的。StringBuilder 是线程不安全的
  3. 基于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

  1. Stack Overflow
    栈溢出问题比较简单,如果递归调用,返回条件没有写好,反复栈帧入栈,就会报错 stack overflow
    出现这个问题后,可以通过 -Xss(stack space) 参数来增加栈的大小
  2. java.lang.OutOfMemoryError: Java heap space 堆内存溢出
    -原因:就是堆内存不够了。
  • 分析:可以使用 jdk 工具, jmap -dump 将java 进程的内存 dump 成一个快照文件,再使用相关的工具 IBM Heap Analyzer 分析这个文件
  • 解决: -Xms(memory space)参数将堆大小增大
  1. java.lang.OutOfMemoryError: Java PermGen space 永久代(方法区)溢出
  • 原因:出现大量的 Classs、出现过多的字符串常量
  • 分析:
  • 解决: -XX:PermSize 调整方法区大小

相关文章

网友评论

      本文标题:Java 基础,常见面试题

      本文链接:https://www.haomeiwen.com/subject/gnskkhtx.html