> 文档中心 > (备战春招,每天进步亿点点)常见面试题总结——Java基础

(备战春招,每天进步亿点点)常见面试题总结——Java基础


大家好,我是杜晓帅~,春招已经开始很久了,从去年的这篇文章立下的flag(不知不觉已经大四了,错过了秋招,春招是该好好把握了),现在也该开始一步一步准备了,我决定将每天所学的知识以博客打卡的方式上传到CSDN以此监督自己,这个名字就叫备战春招,每天进步亿点点吧

在这里插入图片描述

文章目录

  • Java基础
    • Java语言有哪些特点?
    • JVM、JRE和JDK的关系是什么?
    • 什么是字节码?
    • Oracle JDK 和 OpenJDK 的区别是什么?
    • 重载(Overload)和重写(Override)的区别是什么?
    • Error 和 Exception 区别是什么?
    • throw 和 throws 的区别是什么?
    • try-catch-finally 中,如果 catch 中 return 了,finally 还会执行吗?
    • Java的IO 流分为几种?
    • BIO、NIO、AIO的区别?

Java基础

Java语言有哪些特点?

  • 面向对象(封装,继承,多态);
  • 平台无关性, 平台无关性的具体表现在于,Java 是“一次编写,到处运行(Write Once,Run any Where)”的语言,因此采用 Java 语言编写的程序具有很好的可移植性,而保证这一点的正是 Java 的虚拟机机制。在引入虚拟机之后,Java 语言在不同的平台上运行不需要重新编译。
  • 可靠性、安全性;
  • 支持多线程。 C++ 语言没有内置的多线程机制,因此必须调用操作系统的多线程功能来进行多线程程序设计,而 Java 语言却提供了多线程支持;
  • 支持网络编程。 Java 语言诞生本身就是为简化网络编程设计的,因此 Java 语言不仅支持网络编程而且很方便;
  • 编译与解释并存;

JVM、JRE和JDK的关系是什么?

JDK是(Java Development Kit)的缩写,它是功能齐全的 Java SDK。它拥有 JRE 所拥有的一切,还有编译器(javac)和工具(如 javadoc 和 jdb)。它能够创建和编译程序。

JRE是Java Runtime Environment缩写,它是运行已编译 Java 程序所需的所有内容的集合,包括 Java 虚拟机(JVM),Java 类库,java 命令和其他的一些基础构件。但是,它不能用于创建新程序。

JDK包含JRE,JRE包含JVM。
在这里插入图片描述

什么是字节码?

  • Java之所以可以“一次编译,到处运行”,一是因为JVM针对各种操作系统、平台都进行了定制,二是因为无论在什么平台,都可以编译生成固定格式的字节码(.class文件)供JVM使用。因此,也可以看出字节码对于Java生态的重要性。
  • 之所以被称之为字节码,是因为字节码文件由十六进制值组成,而JVM以两个十六进制值为一组,即以字节为单位进行读取。在Java中一般是用javac命令编译源代码为字节码文件,一个.java文件从编译到运行的示例如图所示。
    在这里插入图片描述

Oracle JDK 和 OpenJDK 的区别是什么?

  • Oracle JDK 版本将每三年发布一次,而 OpenJDK 版本每三个月发布一次;
  • OpenJDK 是一个参考模型并且是完全开源的,而 Oracle JDK 是OpenJDK 的一个实现,并不是完全开源的;
  • Oracle JDK 比 OpenJDK 更稳定。OpenJDK 和 Oracle JDK 的代码几乎相同,但 Oracle JDK 有更多的类和一些错误修复。因此,如果您想开发企业/商业软件,建议选择 Oracle JDK,因为它经过了 彻底的测试和稳定。某些情况下,有些人提到在使用 OpenJDK 可能会遇到了许多应用程序崩溃的问题,但是,只需切换到 Oracle JDK 就可以解决问题;
  • 在响应性和 JVM 性能方面,Oracle JDK 与 OpenJDK 相比提供了更好的性能;
  • Oracle JDK 不会为即将发布的版本提供长期支持,用户每次都必须通过更新到最新版本获得支持来获取最新版本;
  • Oracle JDK 根据二进制代码许可协议获得许可,而 OpenJDK 根据 GPLv2 许可获得许可。

重载(Overload)和重写(Override)的区别是什么?

  • 方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性。
  • 重写发生在子类与父类之间, 重写方法返回值和形参都不能改变,与方法返回值和访问修饰符无关,即重载的方法不能根据返回类型进行区分。即外壳不变,核心重写!
  • 重载(overloading) 是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表。最常用的地方就是构造器的重载。
    在这里插入图片描述

Error 和 Exception 区别是什么?

Java 中,所有的异常都有一个共同的祖先 java.lang 包中的 Throwable 类。Throwable 类有两个重要的子类 Exception(异常)和 Error(错误)。

ExceptionError 二者都是 Java 异常处理的重要子类,各自都包含大量子类。

  • Exception :程序本身可以处理的异常,可以通过 catch 来进行捕获,通常遇到这种错误,应对其进行处理,使应用程序可以继续正常运行。Exception 又可以分为运行时异常(RuntimeException, 又叫非受检查异常)和非运行时异常(又叫受检查异常) 。
  • Error :Error 属于程序无法处理的错误 ,我们没办法通过 catch 来进行捕获 。例如,系统崩溃,内存不足,堆栈溢出等,编译器不会对这类错误进行检测,一旦这类错误发生,通常应用程序会被终止,仅靠应用程序本身无法恢复。
    在这里插入图片描述

throw 和 throws 的区别是什么?

Java 中的异常处理除了包括捕获异常和处理异常之外,还包括声明异常和拋出异常,可以通过 throws 关键字在方法上声明该方法要拋出的异常,或者在方法内部通过 throw 拋出异常对象。

throws 关键字和 throw 关键字在使用上的几点区别如下:

  • throw 关键字用在方法内部,只能用于抛出一种异常,用来抛出方法或代码块中的异常,受查异常和非受查异常都可以被抛出。
  • throws 关键字用在方法声明上,可以抛出多个异常,用来标识该方法可能抛出的异常列表。一个方法用 throws 标识了可能抛出的异常列表,调用该方法的方法中必须包含可处理异常的代码,否则也要在方法签名中用 throws 关键字声明相应的异常。

例如:
throw 关键字:

public static void main(String[] args) { String s = "abc"; if(s.equals("abc")) {     throw new NumberFormatException(); } else {     System.out.println(s); } //function();}

throws 关键字:

public static void function() throws NumberFormatException{ String s = "abc"; System.out.println(Double.parseDouble(s));    } public static void main(String[] args) { try {     function(); } catch (NumberFormatException e) {     System.err.println("非数据类型不能转换。");     //e.printStackTrace(); }}

try-catch-finally 中,如果 catch 中 return 了,finally 还会执行吗?

会执行,在 return 前执行。

在 finally 中改变返回值的做法是不好的,因为如果存在 finally 代码块,try中的 return 语句不会立马返回调用者,而是记录下返回值待 finally 代码块执行完毕之后再向调用者返回其值,然后如果在 finally 中修改了返回值,就会返回修改后的值。显然,在 finally 中返回或者修改返回值会对程序造成很大的困扰,Java 中也可以通过提升编译器的语法检查级别来产生警告或错误。 代码示例1:

public static int getInt() {    int a = 10;    try { System.out.println(a / 0); a = 20;    } catch (ArithmeticException e) { a = 30; return a; /*  * return a 在程序执行到这一步的时候,这里不是return a 而是 return 30;这个返回路径就形成了  * 但是呢,它发现后面还有finally,所以继续执行finally的内容,a=40  * 再次回到以前的路径,继续走return 30,形成返回路径之后,这里的a就不是a变量了,而是常量30  */    } finally { a = 40;    }    return a;}//执行结果:30

代码示例2:

public static int getInt() {    int a = 10;    try { System.out.println(a / 0); a = 20;    } catch (ArithmeticException e) { a = 30; return a;    } finally { a = 40; //如果这样,就又重新形成了一条返回路径,由于只能通过1个return返回,所以这里直接返回40 return a;     }}// 执行结果:40

Java的IO 流分为几种?

  • 按照流的方向:输入流(inputStream)和输出流(outputStream);
  • 按照实现功能分:节点流(可以从或向一个特定的地方读写数据,如 FileReader)和处理流(是对一个已存在的流的连接和封装,通过所封装的流的功能调用实现数据读写, BufferedReader);
  • 按照处理数据的单位: 字节流和字符流。分别由四个抽象类来表示(每种流包括输入和输出两种所以一共四个):InputStream,OutputStream,Reader,Writer。Java中其他多种多样变化的流均是由它们派生出来的。

在这里插入图片描述

BIO、NIO、AIO的区别?

  • BIO: 同步并阻塞,在服务器中实现的模式为一个连接一个线程。也就是说,客户端有连接请求的时候,服务器就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然这也可以通过线程池机制改善。BIO一般适用于连接数目小且固定的架构,这种方式对于服务器资源要求比较高,而且并发局限于应用中,是JDK1.4之前的唯一选择,但好在程序直观简单,易理解。
  • NIO: 同步并非阻塞,在服务器中实现的模式为一个请求一个线程,也就是说,客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到有连接IO请求时才会启动一个线程进行处理。NIO一般适用于连接数目多且连接比较短(轻操作)的架构,并发局限于应用中,编程比较复杂,从JDK1.4开始支持。
  • AIO: 异步并非阻塞,在服务器中实现的模式为一个有效请求一个线程,也就是说,客户端的IO请求都是通过操作系统先完成之后,再通知服务器应用去启动线程进行处理。AIO一般适用于连接数目多且连接比较长(重操作)的架构,充分调用操作系统参与并发操作,编程比较复杂,从JDK1.7开始支持。

Java基础就写到这了,如果都各位有用的话请三连支持一下(以便于回访),蟹蟹!

在这里插入图片描述