万字干货|Java基础面试题(2022版)

作者:小牛呼噜噜 | https://xiaoniuhululu.com
计算机内功、JAVA底层、面试相关资料等更多精彩文章在公众号「小牛呼噜噜 」

概念常识

Java 语言有哪些特点?

  1. 简单易学

Java 会让你的工作变得更加轻松,使你把关注点放在主要业务逻辑上
尤其是Java语言 没有指针,并提供了 自动的垃圾回收机制,使得程序员不必为内存管理而担忧

  1. 面向对象

具有代码扩展,代码复用等功能,其三大核心概念: 封装,继承,多态
详情见:https://mp.weixin.qq.com/s/Q1hABlF4kBhcyf3vnLrtFQ

  1. 支持多平台

在一个平台上编写的任何应用程序都可以轻松移植到另一个平台上, 是Java 虚拟机实现平台无关性

  1. 安全性

Java 被编译成 字节码,由 Java 运行时环境解释。编译后会将所有的代码转换为字节码,人类无法读取。它使开发无病毒,无篡改的系统/应用成为可能

  1. 健壮性

Java 有强大的内存管理功能,在编译和运行时检查代码,它有助于消除错误。

  1. 支持多线程

多线程是指允许一个应用程序同时存在两个或两个以上的线程,用于支持事务并发和多任务处理。
C++ 语言没有内置的多线程机制,因此必须调用操作系统的多线程功能来进行多线程程序设计,而 Java 语言却提供了多线程支持
Java除了内置的多线程技术之外,还定义了一些类、方法等来建立和管理用户定义的多线程。

  1. 动态性

它具有适应不断变化的环境的能力,Java程序需要的类能够动态地被载入到运行环境,也可以通过网络来载入所需要的类。它能够支持动态内存分配,从而减少了内存浪费,提高了应用程序的性能。

  1. 分布式

Java 提供的功能有助于创建分布式应用。使用 远程方法调用(RMI),程序可以通过网络调用另一个程序的方法并获取输出。您可以通过从互联网上的任何计算机上调用方法来访问文件。这是革命性的一个特点,对于当今的互联网来说太重要了。

  1. 高性能

Java 最黑的科技就是字节码编程,Java 代码编译成的字节码可以轻松转换为本地机器代码。
如果解释器速度不慢,Java可以在运行时直接将目标代码翻译成机器指令,翻译目标代码的速度与C/C++的性能没什么区别。通过 JIT 即时编译器来实现高性能。

JVM、JRE和JDK的关系

  • JVM

Java 虚拟机(JVM)是运行 Java 字节码的虚拟机,Java程序需要运行在虚拟机上,不同的平台有自己的虚拟机,JVM在执行字节码时,把字节码解释成具体平台上的机器指令执行。这就是Java的能够”一次编译,到处运行”的原因。因此Java语言可以实现跨平台。
字节码和不同系统的 JVM 实现是 Java 语言”一次编译,随处可以运行”的关键所在。
只要满足 JVM 规范,任何公司、组织或者个人都可以开发自己的专属 JVM。

  • JRE

JRE(Java Runtime Environment)是 Java 运行时环境。包括Java虚拟机和Java程序所需的核心类库等。核心类库主要是java.lang包:包含了运行Java程序必不可少的系统类,如基本数据类型、基本数学函数、字符串处理、线程、异常处理类等,但是系统缺省加载这个包,不能用于创建新程序。

  • JDK

Java Development Kit是提供给Java开发人员使用的,其中包含了Java的开发工具,也包括了JRE。所以安装了JDK,就无需再单独安装JRE了。其中的开发工具:编译工具(javac.exe),打包工具(jar.exe)等,它能够创建和编译程序。

万字干货|Java基础面试题(2022版)

什么是字节码?

字节码:Java源代码编译后产生的文件(即扩展名为.class的文件)。

.java源码是给人类读的,而.class字节码只面向JVM(Java虚拟机)

采用字节码的好处:

  • Java语言通过字节码的方式,在一定程度上解决了传统解释型语言执行效率低的问题,同时又保留了解释型语言可移植的特点。所以Java程序运行时比较高效的(但和无需GC的语言 c、c++、rust等的运行效率还是有所差距)
  • 由于字节码并不针对一种特定的机器,因此,Java 程序无须重新编译便可在多种不同操作系统的计算机上运行。

一般Java程序运行的流程:

Java源代码—->编译器—->jvm可执行的Java字节码(即虚拟指令)—->jvm—->jvm中解释器—–>机器可执行的二进制机器码—->程序运行

万字干货|Java基础面试题(2022版)

为什么说 Java 语言是”编译与解释并存”?

由于计算机只看得懂0100011机器码,语言像C语言,是给人看的。我们通过这些语言编写出来的代码,需要先转换成机器码,然后计算机才能去执行。

  • 编译型 :先将源代码一次性转换成另一种相对来说更低级的语言(字节码,汇编,机器码…),计算机再去执行。常见的编译性语言有 C、C++、Go、Rust 等等。

注意这边的机器码 是代码对应的平台计算机的机器码

  • 解释型 :解释器动态将代码逐句解释(interpret)为机器码(编译器自身的机器码)并运行(边解释边执行)。常见的解释性语言有 Python、JavaScript、PHP 等等。

为什么经常说java是解释性语言也是编译型语言?

JVM的类加载器首先加载字节码文件,然后通过解释器逐行解释执行,每次执行都需要加载、解析,速度慢,还有热点代码重复加载问题。所以引进了JIT编译器(运行时编译),JIT完成一次编译后会将字节码对应的机器码保存下来,下次直接执行。

解释和编译都只是程序从源码到运行时的一种动作,跟语言本身无关,所以我们无需过于纠结这个问题!

Oracle JDK 和OpenJDK的区别

Java最早由SUN公司(Sun Microsystems,发起于美国斯坦福大学,SUN是Stanford University Network的缩写)发明,2006年SUN公司将Java开源,此时的JDK即为OpenJDK。
OpenJDK是Java SE的开源实现,他由SUN和Java社区提供支持,2009年Oracle收购了Sun公司,自此Java的维护方之一的SUN也变成了Oracle。
大多数JDK都是在OpenJDK的基础上编写实现的,比如IBM J9,Azul Zulu,Azul Zing和Oracle JDK。几乎现有的所有JDK都派生自OpenJDK,
他们之间不同的是许可证:

  • OpenJDK根据许可证GPL v2发布。
  • Oracle JDK根据Oracle二进制代码许可协议获得许可。

Oracle JDK 比 OpenJDK 更稳定。在响应性和JVM性能方面,Oracle JDK与OpenJDK相比提供了更好的性能
OpenJDK和Oracle JDK的代码几乎相同,但Oracle JDK有更多的类和一些错误修复。

OpenJDK 是一个参考模型并且是完全开源的,
但是Oracle JDK是OpenJDK的一个实现, 并不是完全开源的

Java 和 C++ 的区别?

Java 和 C++ 都是面向对象的语言,都支持封装、继承和多态,但是它们还是有挺多不相同:

  • Java 不提供指针来直接访问内存,程序内存更加安全
  • Java 的类是单继承的,C++ 支持多重继承;虽然 Java 的类不可以多继承,但是接口可以多继承。
  • Java 有自动内存管理垃圾回收机制(GC),不需要程序员手动释放无用内存。
  • 等等

什么是JIT?

JIT是just in time的缩写,也就是 即时编译。通过JIT技术,能够做到Java程序执行速度的加速。

Java通过编译器javac先将源程序编译成与平台无关的Java字节码文件(.class),再由JVM解释执行字节码文件,从而做到平台无关。 但是,有利必有弊。对字节码的解释执行过程实质为:JVM先将字节码翻译为对应的机器指令,然后执行机器指令。很显然,这样经过解释执行,其执行速度必然不如直接执行二进制字节码文件。

而为了提高执行速度,便引入了 JIT 技术。当JVM发现某个方法或代码块运行特别频繁的时候,就会认为这是”热点代码”(Hot Spot Code)。然后JIT会把部分”热点代码”编译成本地机器相关的机器码,并进行优化,然后再把编译后的机器码缓存起来,以备下次使用。

Java关键字

final finally finalize区别

final可以修饰类、变量、方法

  • 修饰类表示该类不能被继承
  • 修饰方法表示该方法不能被重写
  • 修饰变量表示该变量是一个常量,不可变,在编译阶段会存入常量池中

finally一般作用在try-catch代码块中,在处理异常的时候,通常我们将一定要执行的代码方法finally代码块
中,表示不管是否出现异常,该代码块都会执行,一般用来存放一些关闭资源的代码。

finalize是一个方法,属于Object类的一个方法,而Object类是所有类的父类,该方法一般由垃圾回收器来调
用,当我们调用System.gc() 方法的时候,由垃圾回收器调用finalize(),回收垃圾,一个对象是否可回收的
最后判断。

聊聊this、super和static关键字

  1. this关键字

this表示当前对象的引用:
this.属性 区别成员变量和局部变量
this.() 调用本类的某个方法
this() 表示调用本类构造方法,只能用在构造方法的第一行语句。
this关键字只能出现在非static修饰的代码中

public class Member {
    String name;
    public void setName(String name) {
        this.name = name;
    }
}
  1. super关键字

super可以理解为是指向自己超(父)类对象的一个”指针”,而这个超类指的是离自己最近的一个父类。:
super.属性 表示父类对象中的成员变量
super.方法()表示父类对象中定义的方法
super() 表示调用父类构造方法
可以指定参数,比如super(“Nanjin”);
任何一个构造方法的第一行默认是super();
可以写上,如果未写,会隐式调用super();
super()只能在构造方法的第一行使用。
this()和super()都只能在构造的第一行出现,所以只能选择其一。
写了this()就不会隐式调用super()。
super 关键字在子类中显式调用父类中被覆盖的非静态成员方法和成员变量

class Father {

  void message() {
    System.out.println("This is Father");
  }

}

class Son extends Father {
  void message() {
    System.out.println("This is son");
  }

  void display() {
    message();
    super.message();
  }

}

class Main {
  public static void main(String args[]) {
    Son s = new Son();
    s.display();
  }

}

结果:

This is son
This is father

  1. static关键字

static的主要意义是在于创建独立于具体对象的域变量或者方法。 以致于即使没有创建对象,也能使用属性和调用方法
static修饰的变量称之为静态变量
被static修饰的变量或者方法是独立于该类的任何对象,即这些变量和方法不属于任何一个实例对象,而是被类的实例对象所共享。
static修饰的方法称之为静态方法
静态方法属于class而不属于实例,因此,静态方法内部,无法访问this变量,也无法访问实例字段,它只能访问静态字段
static修饰的代码块叫做静态代码块。

被static修饰的变量或者方法是优先于对象存在的,也就是说当一个类加载完毕之后,即便没有创建对象,也可以去访问。用法:”类.静态变量”

  1. 能否在static环境中访问非static变量?
不能, static方法中不能使用this和super关键字,不能调用非static方法,只能访问所属类的静态成员和静态方法,因为当static方法被调用时,这个类的对象可能还没被创建,即使已经被创建了,也无法确定调用哪个对象的方法。同理,static方法也不能访问非static类型的变量。
  1. this与super关键字的区别

  2. this 表示当前对象的引用,可以理解为指向对象本身的一个”指针”,但是JAVA中是没有指针这个概念的。

  3. super 表示自己超(父)类对象的引用,可以理解为是指向自己超(父)类对象的一个指针,而这个超类指的是离自己最近的一个父类。
  4. super()在子类中调用父类的构造方法,this()在本类内调用本类的其它构造方法。
  5. this和super不能同时出现在一个构造函数里面,因为this必然会调用其它的构造函数,其它的构造函数必然也会有super语句的存在,所以在同一个构造函数里面有相同的语句,就失去了语句的意义,编译器也不会通过。

相同点:

super()和this()均需放在构造方法内第一行。
this()和super()都指的是对象,所以,均不可以在static环境中使用。包括:static变量,static方法,static语句块。

拓展:https://mp.weixin.qq.com/s/tsbDfyYLqr3ctzwHirQ8UQ

Java 有没有 goto

goto 是 Java 中的保留字,在目前版本的 Java 中没有使用。

基础语法

Java 中的基本数据类型有哪些?

Java 中有 8 种基本数据类型,分别为:

基本类型 位数 字节 默认值 包装类 取值范围 byte 8 1 0 Byte -128 ~ 127 short 16 2 0 Short -32768 ~ 32767 int 32 4 0 Integer -2147483648 ~ 2147483647 long 64 8
0L

Long -9223372036854775808 ~ 9223372036854775807 char 16 2 ‘u0000’ Character 0 ~ 65535 float 32 4
0f

Float 1.4E-45 ~ 3.4028235E38 double 64 8
0d

Double 4.9E-324 ~ 1.7976931348623157E308 boolean 1

false Boolean true、false

其中:

char a = ‘hello’; 单引号
String a = “hello” ;双引号

包装类型的缓存机制

Java 基本数据类型的包装类型的大部分都用到了缓存机制来提升性能:
Byte,Short,Integer,Long 这 4 种包装类默认创建了数值 [-128,127] 的相应类型的缓存数据,如果 超出对应范围仍然 会去创建新的对象
另外两种浮点数类型的包装类 Float,Double 并没有实现缓存机制。

Integer i1 = 10;
Integer i2 = 10;
Integer i3 = 200;
Integer i4 = 200;
System.out.println(i1 == i2);// 输出 true
System.out.println(i3 == i4);// 输出 false

什么是自动类型转换、强制类型转换?

Java 数值型变量经常需要进行相互转换,当把⼀个表数 范围⼩的数值或变量直接赋给另⼀个表 数 范围⼤的变量时,可以进⾏ ⾃动类型转换,即 隐式转换

long l = 100;

int i = 200;
long ll = i;

反之,需要 强制类型转换(显式转换)

short s = 199;
int i = s;// 199

double d = 10.24;
long ll = (long) d;// 10, 精度丢失

自动类型转换规则如下:

  • 数值型数据的转换:byte→short→int→long→float→double。
  • 字符型转换为整型:char→int。

一些常见的易错题:

  1. float f=3.4; 程序正确吗?

3.4 是单精度数,将双精度型(double)赋值给浮点型(float)属于下转型会造成精度损失,因此需要强制类型转换 float f =(float)3.4; 或 者写成 float f =3.4F;

  1. short s1 = 1; s1 = s1 + 1; 对吗? short s1 = 1; s1 += 1;对吗?

对于 short s1 = 1; s1 = s1 + 1;编译出错,由于 1 是 int 类型,因此 s1+1 运算结果也是 int型, 需要强制转换类型才能赋值给 short 型。
short s1 = 1; s1 += 1;可以正确编译,因为 s1+= 1;相当于 s1 = (short(s1 + 1);其中有隐含的强 制类型转换。

  1. int count = 100000000; int price = 1999; long totalPrice = count * price;正确吗?

不正确,编译没任何问题,但结果却输出的是负数,这是因为两个 int 相乘得到的结果是 int, 相乘的结果超出了 int 的代表范围。这种情况,一般把第一个数据转换成范围大的数据类型再和其他的数据进行运算。

Math.round(11.5) 等于多少?Math.round(-11.5)等于多少

四舍五入的原理是在参数上加 0.5 然后进行下取整。

  1. Math.round(11.5)的返回值是 12
  2. Math.round(-11.5)的返回值是-11

用最有效率的方法计算 2 乘以 8

2 << 3(左移 3 位相当于乘以 2 的 3 次方,右移 3 位相当于除以 2 的 3 次方)。

运算符 | 和 ||,& 和 && 的区别

|& 定义为位运算符。
||&& 定义为逻辑运算符,

& 按位与操作,按二进制位进行” “运算。运算规则:(有 0 则为 0)
| 按位或运算符,按二进制位进行” “运算。运算规则:(有 1 则为 1)

`java
A = 0011 1100
B = 0000 1101

Original: https://www.cnblogs.com/xiaoniuhululu/p/16469781.html
Author: 小牛呼噜噜
Title: 万字干货|Java基础面试题(2022版)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/577872/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • Vim 文本替换介绍与使用

    range 作用范围 空 # 默认为光标所在的行 . # 光标所在的行 n # 第 n 行(1表示第 1行,10表示第 10行),可使用:set nu 显示vim行号 $ # 最后…

    Linux 2023年6月6日
    090
  • windows下redis配置密码

    redis安装后目录如下: 最简单的启动方式是直接双击redis-server.exe 这样启动会有个问题,一旦你把命令行窗口关闭 redis也会被关闭,所以我们需要把它注册成服务…

    Linux 2023年5月28日
    0101
  • Docker安装及配置镜像加速

    Docker 支持 Mac Windows Linux 的三种安装 1、系统要求 官网提示如果要安装 Docker Engine, 需要一个CentOS 7 以及以上的稳定版本。 …

    Linux 2023年5月27日
    0106
  • 十二、启动流程

    启动流程介绍 现代计算机系统启动是硬件与软件复杂组合。从定义的端点开始,到拥有登录提示符的运行中系统,需要大量的硬件和软件配合工作。以下列表从较高层面概述了启动系统时所涉及的任务。…

    Linux 2023年6月7日
    0101
  • 什么是守护进程?

    在了解守护进程之前,需要先知道什么是什么是终端?什么是作业?什么是进程组?什么是会话? 在 Linux 中, 每一个系统与用户进行交流的界面称为终端,每一个从此终端开始运行的进程都…

    Linux 2023年6月8日
    0115
  • 操作系统实战45讲-10 设置工作模式与环境:建立计算机

    实验环境: 虚拟机软件:VMware® Workstation 16 Pro虚拟机:Ubuntu 20.04 生产虚拟硬盘 用 dd 命令(用指定大小的块拷贝一个文件,并在拷贝的同…

    Linux 2023年6月7日
    0110
  • 使用PowerShell收集多台服务器的性能计数器

    写在前面 当管理多台Windows Server服务器时(无论是DB、AD、WEB以及其他的应用服务器),当出现性能或其他问题后,参阅性能计数器都是一个非常好的维度从而推测出问题可…

    Linux 2023年5月28日
    089
  • Redis 事务

    一、概述 和传统关系型数据库一样,Redis 同样是支持事务的。Redis 的事务可以通过 MULTI/EXEC/DISCARD/WATCH 等命令来实现。 二、事务的 ACID …

    Linux 2023年5月28日
    099
  • 使用 sh -x 进行 shell 脚本调试

    转载请注明出处: sh -x 命令的执行,会将shell 命令的每一个执行步骤进行打印,可以查看到 整个命令或脚本的执行过程的 debug。 sh -n 只读取shell脚本,检测…

    Linux 2023年5月28日
    0116
  • RAID级别

    常用选项 模式: 创建:-C 装配:-A 监控:-F 管理:-f, -r, -a < raiddevice> : /dev/md# < component-dev…

    Linux 2023年6月6日
    091
  • 选择排序算法C语言实现

    选择排序C语言实现 int select_sort(int *list, int len) { int i = 0; int j = 0; int tmp = 0; int sma…

    Linux 2023年6月14日
    080
  • [ Python ] PyQt5 PySide2 笔记

    https://www.cnblogs.com/yeungchie/ PyQt5 from PyQt5.QtWidgets import * from PyQt5.QtCore i…

    Linux 2023年6月7日
    098
  • 解决关闭shell会话窗口则会发现ASP.NET Core应用也会被关闭问题

    统计了三种方法: 一、使用nohup命令即可 【最简单】 nohup dotnet xxxx.dll 【xxxx为应用名称】 一般会报:nohup: ignoring input …

    Linux 2023年6月8日
    0121
  • 常见开发模型-敏捷开发与瀑布开发模型详解

    引言 在学习软件工程的时候接触过一些软件工程开发模型的相关概念,其中,印象比较深刻的就是瀑布模型和敏捷开发模型。这两种模型在日常的软件开发中都是非常常用的,但是它们也有比较大的区别…

    Linux 2023年6月7日
    0132
  • python语法01

    在某.py文件中调用其他.py文件中的内容。全局变量的使用。线程的使用。if name == ‘ main‘: 的作用新建两个python脚本文件f1Fil…

    Linux 2023年6月14日
    086
  • 高等代数: 2 行列式

    2 行列式 1、n个不同的自然数的一个全排列称为一个n元排列。 2、顺序、逆序、逆序数:τ(abcd…)(读音:tao)、奇排列、偶排列、对换(a,b) 3、定理1:对…

    Linux 2023年6月8日
    0147
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球