【学习笔记】Java基础面试题

116 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第10天,点击查看活动详情

Java基础面试题(下)

异常

Exception和Error有什么区别?

都继承Throwable类。

Exception:程序本身可以处理的异常,可以使用catch来进行捕获。Exception又分为受检异常(必须进行处理)和不受检异常(可以不进行处理)。

Checked Exception 和 Unchecked Exception 有什么区别?

  • Checked Exception 即 受检查异常 ,Java 代码在编译过程中,如果受检查异常没有被 catch或者throws 关键字处理的话,就没办法通过编译。【ClassNotFoundException、SQLException】
  • Unchecked Exception不受检查异常 ,Java 代码在编译过程中 ,我们即使不处理不受检查异常也可以正常通过编译。【RuntimeException及其子类(NullPointException、ClassCastException、ArrayIndexOutOfBoundsException)】

Throwable 类常用方法有哪些?

  • String getMessage(): 返回异常发生时的简要描述
  • String toString(): 返回异常发生时的详细信息
  • void printStackTrace(): 在控制台上打印异常时的出错位置和原因等,更加详细。

try-catch-finally 如何使用?

  • try块 : 用于捕获异常。其后可接零个或多个 catch 块,如果没有 catch 块,则必须跟一个 finally 块。
  • catch块 : 处理 try 捕获到的异常
  • finally 块 : 无论是否捕获或处理异常,finally 块里的语句都会被执行。

finally 中的代码一定会执行吗?

不一定。在某些情况下,finally 中的代码不会被执行。

就比如说 finally 之前虚拟机被终止运行的话,finally 中的代码就不会被执行。

如何使用 try-with-resources 代替try-catch-finally

面对必须要关闭的资源,优先使用try-with-resources。将创建的IO流等必须要关闭的资源写在try的括号中即可。

try (Scanner scanner = new Scanner(new File("test.txt"))) {
    while (scanner.hasNext()) {
        System.out.println(scanner.nextLine());
    }
} catch (FileNotFoundException fnfe) {
    fnfe.printStackTrace();
}

异常使用有哪些需要注意的地方?

  • 每次手动抛出异常,都需要手动 new 一个异常对象抛出。
  • 抛出更具体,有意义的异常。
  • 使用日志打印异常之后就不要再抛出异常了(两者不要同时存在一段代码逻辑中)。

泛型

什么是泛型?有什么作用?

泛型可以增强代码的可读性以及稳定性。可读性:不需要强制类型转换,编译器就知道返回值的类型。

安全性/稳定性:增加了类型检测,比如List在插入元素时,编译器可以对泛型参数进行检测,如果传入其他类型就会报错。

泛型的使用方式有哪几种?

泛型类(泛型写在类名后)、泛型接口(泛型写在接口名后)、泛型方法(泛型写在返回参数处)。

反射

什么是反射?

很多框架的底层都一定会使用到反射。反射被称为框架的灵魂。通过使用反射,我们可以获取任意一个类的所有属性和方法,还可以调用这些属性和方法。

反射的优缺点?

优点:可以让代码更加灵活,很多框架也使用了反射。

缺点:可以无视泛型参数的安全检查(泛型参数的安全检查发生在编译时)。

反射的应用场景?

像 Spring/Spring Boot、MyBatis 等等框架中都大量使用了反射机制。

  1. Spring中的动态代理就使用了反射,可以通过反射获取目标对象的目标方法。
  2. 注解的实现也用到了反射。

注解

什么是注解?

注解是Java5开始引入的新特性,可以用于修饰类、方法、变量,提供程序运行需要的信息。

本质是继承了Annotation的特殊接口。

注解的解析方法有哪几种?

  • 编译期直接扫描:比如@Override注解,编译器在编译时就会检测当前方法是否重写了父类的方法。
  • 运行期通过反射处理:框架中自带的注解都是通过反射来进行处理的。

SPI

什么是SPI?

服务提供者的接口,也就是专门提供给开发者去使用的一个接口。

可以将接口和具体的服务分离开来,修改或者替换服务不需要修改调用方。

SPI和API的区别?

API:实现方(被调用方)提供接口和具体的实现,我们可以通过调用实现方的接口,从而获得具体的功能,这种就是API,接口和实现都是在实现方

img

SPI:当接口存在与调用方这边,就是SPI,由接口调用方确认接口规则,之后由实现方去根据规则进行实现,从而提供服务。

  • 例子:

    Spring日志服务就是一个接口,具体实现可以有很多:Log4j、Log4j2等。在切换日志具体实现的时候我们是不需要更改项目代码的,只需要在 Maven 依赖里面修改一些 pom 依赖就好了。