万字干货|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/617160/

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

(0)

大家都在看

  • 源码中的设计模式–装饰器模式

    一、模式入场 有一句很经典的小品台词是”换个马甲我就不认识你了吗”,哈哈,这个比方正好用在今天要分享的装饰器模式上。先看下《head first 设计模式》…

    Java 2023年6月9日
    073
  • Tomcat、Nginx/Openresty 隐藏版本号,使用nginx来统一显示错误页面

    默认报错页面信息会暴露出版本号 进入tomcat的lib目录找到catalina.jar文件 unzip catalina.jar之后会多出两个文件夹 进入org/apache/c…

    Java 2023年5月30日
    073
  • equals && deepEquals

    equals && deepEquals 本文分为以下几个部分 equals deepEquals 首先说明:这里说的 equals 是 java.util.Arr…

    Java 2023年6月5日
    067
  • 记一次数据库查询超时优化问题

    问题发现 在七月份时,经常发现有几个定时任务报错,查看了下异常原因,大概定位是数据库执行异常 ### Error querying database. Cause: com.mys…

    Java 2023年6月5日
    074
  • Java Lambda基础——Function, Consumer, Predicate, Supplier, 及FunctionalInterface接口

    这几个接口经常与Lambda结合使用,网上当然也有很多介绍,不过有些过于繁琐,有些又偏简单,秉着实用主义精神,今天这里折中一下,把介绍的内容分为两部分,第一部分相当于TLDR,总结…

    Java 2023年5月29日
    067
  • java并发体系

    posted @2022-02-17 11:37 雄狮_杜 阅读(11 ) 评论() 编辑 Original: https://www.cnblogs.com/duyinqiang…

    Java 2023年5月29日
    081
  • 数据结构——稀疏数组

    数据结构——稀疏数组 棋局存档问题:如何将一局五子棋保存下来,并实现读档 利用稀疏数组进行数据保存,IO流写入/读取文件,实现读档。 简单代码实现: /** * @author 萝…

    Java 2023年6月9日
    071
  • java-单例详解

    一. 什么是单例模式 因程序需要,有时我们只需要某个类同时保留一个对象,不希望有更多对象,此时,我们则应考虑单例模式的设计。 二. 单例模式的特点 单例模式只能有一个实例。 单例类…

    Java 2023年6月8日
    071
  • SpringCloud之Seata

    1.Seata是什么? 1.1 概念:Seata 是一款开源的分布式事务解决方案,提供高性能和简单易用的分布式事务服务。1.2 术语(1)TC: 事务协调者维护全局和分支事务的状态…

    Java 2023年6月13日
    048
  • mybatis insert返回主键的三种方式

    1.情景展示 我们知道,表与表之间的关联关系,通常使用主键,所以在处理复杂业务时,比如:按顺序插入多张表; 我们就需要在插入B表之间拿到插入A表后的主键,如何实现? 2.具体实现 …

    Java 2023年5月30日
    071
  • 复杂类型注入

    java;gutter:true; /</p> <pre><code> ;gutter:true;/java;gutter:true; valu…

    Java 2023年6月13日
    058
  • ES基本语法的Java客户端操作

    先准备一份数据库和表 创建一个对应的实体类 这里的案例使用测试类进行 1.增删改和简单查 API java连接至es 增删改 和简单查 2.复杂查询 核心对象 对象关系 Searc…

    Java 2023年5月29日
    059
  • 二、在SSM框架中简单使用mybatis

    1.要使用mybatis,首先准备配置文件。 本文以idea的Maven为例 1.将以下依赖项导入Maven项目中的pom.xml 2.在项目的Src/main/resources…

    Java 2023年5月29日
    079
  • redis事务和锁机制、持久化操作RDB/AOF

    一、Redis事务介绍 Redis事务是一个单独的 隔离操作 :事务中的所有命令都会 序列化、 按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。Redis…

    Java 2023年6月8日
    063
  • 洛谷P3366 【模板】最小生成树(Boruvka算法)

    题意 题目链接 Sol 自己yy着写了一下Boruvka算法。 算法思想很简单,就是每次贪心的用两个联通块之间最小的边去合并。 复杂度(O(n \log n)),然鹅没有Krusk…

    Java 2023年5月30日
    095
  • 简明 Java 错误处理机制

    用个最简单的例子来展示为什么需要错误处理,以及怎么用。 import java.io.FileInputStream; import java.io.FileNotFoundExc…

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