Java高频出现的面试题

Java面试干货

简述:本文涵盖了JavaSE,JavaEE,数据库,框架等方面的知识点,包括JVM、JIT和AOT、编译性语言和解释性语言区别、常见异常、集合、Spring、数据库范式、事务特征、索引、SpringBoot、IOC、AOP、Vue生命周期、跨域问题、悲观锁和乐观锁等。内容全面,涵盖面广,有助于对Java面试干货的全面了解。

文章目录

JavaSE

javaSE和JavaEE

**javaSE:**是Java的基础版本。跟家偏向于开发一些桌面应用程序,和简单的服务器程序。

JavaEE:是在SE的基础上进行了功能性的增强,比如有(Servlet、JSP、EJB、JDBC、JPA、JTA、JavaMail、JMS)。用于开发复杂的业务和Web应用程序。

jdk jre jvm

jdk是开发工具类包,包含了运行环境和开发

jre是运行环境和核心类库

jvm是Java的虚拟机

JVM是什么

jvm是虚拟出来的计算机,所以也叫JVM虚拟机。

JVM负责将编译好的class文件,编译成机器码运行在各个系统程序上运行。达到了高可移植性,只有生成了.class文件,就可以在多个平台上运行

在这里插入图片描述

JVM内存结构

  1. 堆(Stack)
    堆是Java虚拟机中用于存储对象实例的内存区域。所有的对象实例以及数组都在堆上分配。堆是Java内存管理中最大的一块区域,也是线程共享的。
  2. 栈(Heap)
    Java虚拟机栈用于存储方法运行时的局部变量、操作数栈、动态链接、方法出口等信息。每个方法执行的同时都会创建一个栈帧用于存储局部变量表、操作数栈、方法出口等信息。栈是线程私有的,每个线程在执行方法时都会创建对应的栈帧。
  3. 方法区(Method Area)
    **方法区存储类中的数据结构、变量、静态变量,编译后数据存储的内存区域。**在方法区中,包含了运行时常量池(存储编译期生成的各种字面量和符号引用)、类信息、字段信息、方法信息、构造函数等。方法区是线程共享的内存区域,它在程序启动时被创建,并且在程序结束时被销毁。
  4. 本地方法栈(Native Method Stack)
    本地方法栈与Java虚拟机栈类似,区别在于本地方法栈是为本地(native)方法服务的。它存储了调用本地方法时的信息。
  5. 程序计数器(Program Counter Register)
    程序计数器是一块较小的内存空间,可以看作是当前线程所执行的字节码的行号指示器。在Java虚拟机的多线程环境下,程序计数器是线程私有的,每个线程都会拥有一个程序计数器
  6. 运行时常量池(Runtime Constant Pool)
    运行时常量池是方法区的一部分,用于存放编译期生成的各种字面量和符号引用。

在JVM内存结构中,以下是私有的部分和共享的部分:
私有部分:

  1. Java虚拟机栈(Stack)

    • 每个线程都有自己的栈,用于存储方法运行时的局部变量、操作数栈、动态链接、方法出口等信息。
  2. 本地方法栈(Native Method Stack)

    • 每个线程拥有自己的本地方法栈,存储本地方法调用相关信息。
  3. 程序计数器(Program Counter Register)

    • 每个线程都有自己的程序计数器,用于存储当前线程执行的字节码行号指示器。

共享部分:

  1. 堆(Heap)

    • 所有线程共享的内存区域,用于存储对象实例和数组。
  2. 方法区(Method Area)

    • 存储类的结构信息、常量、静态变量、即时编译器编译后的代码等数据。
    • 运行时常量池等。
    • 是所有线程共享的。

JIT和AOT

为了加快代码的运行速度,JIT会把热点代码会在JVM编译class文件为机器码的时候给记录下来。下次运行可以直接运行机器码,速度会更加快。

JIT采用的是延迟评估(Lazy Evaluation)的做法,每次执行的时候收集运行信息。把常用到的热点代码给记录下来,所以Java代码会越执行越快。

AOT是JDK 9引入的一种新的编译模式,和JIT不同的是。他会在程序被执行前就将其编译成机器码。提高Java的启动速度,减少内存占用增强Java的安全性(AOT 编译后的代码不容易被反编译和修改)但它只是在系统执行之前进行操作的

在这里插入图片描述

编译性语言和解释性语言区别

编译性语言:将代码全部转换为机器码,给设备进行运行。开发效率慢,运行速度快。比如:C,C++,Rust

解释性语言:将代码一句一句的解释为机器代码后在进行执行。开发效率快,运行速度慢。比如:Java,python,PHP

但是现在Java已经具备这两个的特征了。因为Java程序要先编译,生成.class文件。然后通过JVM进行解释

Java常用的6个包

  • java.lang
    • 包含了Java中基本的数据包装类型,String,Object
    • 提供了Java语言的基本支持。
  • java.util
    • 包含了集合框架日期时间处理随机数生成器Scanner等常用的实用工具类。
  • java.io
    • 提供了对系统输入输出的支持,包括文件读写、流处理等。
  • java.net
    • 包含网络编程相关的类,用于实现网络通信、Socket编程、URL处理等。
  • java.sql
    • 包含了Java对于数据连接的相关类,用于对数据库交互
  • java.awt和java.swing
    • 抽象窗口工具类,用于创建图形用户界面(GUI)应用程序的基本组件和功能。
    • 建立在java.awt之上的,提供了更丰富的GUI组件,用于创建现代化的GUI应用程序。

标识符和关键字的区别

标识符:是指为类,方法名,变量取名的。这就叫标识符

关键字:系统中的有特殊含义和使用方法的名称,如IF,FOR等等。也被称作特殊的标识符

JAVA和C++的区别

相同:Java 和 C++ 都是面向对象的语言,都支持封装、继承和多态

不同:

  • Java不提供指针直接访问内存
  • Java的类只能单继承,接口可以多继承。C++可以多继承
  • Java有垃圾回收机制(GC)
  • Java和C++都可以进行方法重载,C++多了一个操作符重载,可以重新定义运算符的规则

对类,方法,变量命名规则

类名大驼峰规则

方法是小驼峰规则

变量是是全小写,常量是全大写

JDK版本区别

JDK8:引入了Lambda表达式、Stream API、新的日期时间API等重要功能。

JDK9:在9往后,就不需要去区分JRE和JDK的关系了,取而代之的是模块系统

Java跳出循环的三种方式

break 跳出循环

retrun 跳出方法

continue 结束本次循环

基本数据类型和引用数据类型

基本数据有四大类,分为字符型,布尔型,浮点型,整形

其中细分有byte,short,int,long(整形),char,Boolean,float,double

为什么取值范围负数会多一个,其实就是符号位被用来做了个补充,用来代表多出来的那个负数!

基本类型和包装类型的区别

在介绍两个之间的区别之前,还有两个概念。拆箱与装箱,拆箱就是包装类型转换为基础类型过程。反之,装箱就是基础类型转换为包装类型的过程。

  • 用途:除去定义基本的变量以外,使用方法形参尽量使用包装类型。因为包装类型可以用于泛型。

  • 存储方式:基本类型的局部变量存放在栈中,成员变量存放在堆当中。而包装类型是对象类型**,所以存放在堆当中。

  • 占用空间:相比于包装类型(对象类型), 基本数据类型占用的空间往往非常小。

  • 默认值:成员变量包装类型不赋值就是 null ,而基本类型有默认值且不是 null

  • 比较方式:对于基本数据类型来说,== 比较的是值。对于包装数据类型来说,== 比较的是对象的内存地址。所有整型包装类对象之间值的比较,全部使用 equals() 方法。

  1. byte:默认值是0
  2. short:默认值是0
  3. int:默认值是0
  4. long:默认值是0L
  5. float:默认值是0.0f
  6. double:默认值是0.0d
  7. char:默认值是’\u0000’,即空字符
  8. boolean:默认值是false

包装类型的缓存机制

Java 基本数据类型的包装类型的大部分都用到了缓存机制来提升性能。

Byte,Short,Integer,Long 这 4 种包装类默认创建了数值 [-128,127] 的相应类型的缓存数据,Character 创建了数值在 [0,127] 范围的缓存数据,Boolean 直接返回 True or False

类型的自动转换

当表达式中,混合多个变量类型。程序将会把所有变量编程容量最大的数据类型进行计算

精度大的变量赋值给小的会报错,反之转换

(byte,short)和char之间不会相互自动转换

boolean不参与转换

引用数据类型和基本数据类型

基本数据类型是直接存储在栈上的,本身就是数据。

引用数据类型,是在堆内存中。开辟了一片空间,对象进行数据的引用。使用了new实际上就是在堆内存中开辟了一片空间,等号位指向。

常见的引用数据类型有:类,数组,字符串

final关键字的作用?

修饰类:类不能被继承

修饰方法:方法不能被重写

修饰变量:基本数据变量值不能被修改,引用数据变量的地址不能被修改。但是地址中的值可以被修改的。

局部变量和成员变量的区别

局部变量创建于代码块中,也只会生效于该代码块中。代码块执行完毕会进行销毁。不会自动进行赋值。

成员变量是写在类内部,方法外面的变量,可以在类中进行使用,或者实例化类后,通过类名调用。如果没有被final修饰,不需要显示的赋值,系统会给默认值。

接口和抽象类的区别

  1. 接口中只有抽象方法,抽象类中由已经实现的方法
  2. 一个类只能继承一个抽象类,但是可以实现多个接口
  3. 抽象类中的成员变量可以是各种类型的,接口中的成员变量只能是public static final类型;
  4. 子类继承抽象类时,必须实现所有抽象方法,除非子类也声明为抽象类。
  5. 类可以实现多个接口,但只能继承一个类。

常见的异常有哪些

  1. ClassCastException 类型转换异常
  2. IndexOutOfBoundsException 数组越界异常
  3. NullPointerException 空指针
  4. SQLException:SQL 异常,通常在数据库操作中抛出。
  5. NoSuchBeanDefinitionException:没有找到bean异常

throw和throws的区别?

throw:抛出一个具体的异常

hrows的:方法声明中指定可能会抛出的异常类型。可能会抛出那些异常

Java8有哪些新特性

  1. Lambda表达式,允许这个函数作为方法的参数
  2. Date Time API :增强了对时间的处理
  3. Optional 类,用来解决空指针异常
  4. Stream API:提供了一个新的方式去处理集合,简化代码提高性能。流式操作

阻塞和非阻塞的区别

这两个东西关注的是线程的状态

阻塞:调用的结果没有返回结果之前,这个线程会被挂起。只有的到返回结果的时候,才恢复运行

非阻塞:不能立刻得到结果的时候,不会阻塞当前的线程

静态方法为什么不能调用非静态的成员

静态方法是属于类的,在类加载的时候。就会分配内存。可以直接通过类名去进行访问。而非静态的成员,需要跟着类的实例化才功能去进行访问和使用。

谈谈对String的理解

String的底层是一个被Final修饰的char数组

初始化String有三种初始化方法,一个直接赋值,一个是无参构造来赋值,一个用有参构造来赋值。存储在内存中的位置不同。

直接赋值看内存有无一样的字符串,没有会进行创建有会直接引用

String str1 = "hello";
String str2 = "hello";
// true
System.out.println(str1 == str2);

使用无参构造创建,后续赋值会查看常量池里面是否有值

String str1 = new String();
String str2 = "hello";
str1 = "hello";
System.out.println(str1 == str2);// true

使用有参构造创建,必须分配内存空间。

String str1 = new String("hello");
String str2 = "hello";
// false
System.out.println(str1 == str2);

i++ 和 ++i

i++ 先执行再加 ++i 先加再执行

集合

集合分为单列集合和双列集合
List接口有ArrayList和LinkedList实现,是有序可重复的。

Set 无序集合,不能重复。实现类有HashSet和LinkedHashSet

Map 键值对集合,是双列集合。

Collection包含了 List和Set子接口,不包括map的接口。

如何集合线程安全

1:可以使用线程安全的集合
比如VectorHashtableConcurrentHashMapCopyOnWriteArrayList
2:使用同步代码块(synchronized)
在多线程环境下,通过同步关键字synchronizedLock接口来保护对集合的访问,确保同一时间只有一个线程可以访问集合,从而保证线程安全性。

List<String> list = new ArrayList<>();

synchronized(list) {
   
   
    // 在同步块内对集合进行操作
}

// 或者使用Lock接口
Lock lock = new ReentrantLock();
lock
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值