欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Java常见面试题(精选36道核心面试题)

程序员文章站 2024-01-11 16:11:52
目录java核心面试题1、java个版本中更新的重要功能1.1 java 14版本中更新的重要功能1.2 java 13版本中更新的重要功能1.3 java12版本中更新的重要功能1.4 java11版本中更新的重要功能1.5 java10版本中更新的重要功能1.6 java9版本中更新的重要功能1.5 java8版本中更新的重要功能2、java面向对象编程的特征3、 [JVM](https://blog.csdn.net/issunmingzhi/article/details/104774941)4、J...


目录


java核心面试题

前段时间归纳总结了计网的面试知识计网面试题,收到了不少的好评,今天来总结下java面试中的核心问题,希望大家能够喜欢。

1、java个版本中更新的重要功能

1.1 java 14版本中更新的重要功能

  • switch表达式
  • instanceof增强表达式,预览功能
  • 文本块,第二次预览
  • Records,预览功能

1.2 java 13版本中更新的重要功能

  • 文本块,预览功能
  • switch表达式,预览功能
  • Java Socket重新实现
  • FileSystems.newFileSystem()方法
  • 支持Unicode 12.1
  • 可伸缩、低延迟的垃圾收集器改进,用于返回为使用的内存

1.3 java12版本中更新的重要功能

  • JVM更新
  • File.mismatch()方法
  • 紧凑型数字格式
  • String类中新增了一些方法,比如说indent()

1.4 java11版本中更新的重要功能

  • 是java8以后的第二个商用版本
  • 可以直接使用java命令运行java程序、源代码将会隐式编译和运行
  • String类新增了两个读写方法,readString()和writeString()
  • 可以在Lamdba表达式中使用var作为变量类型

1.5 java10版本中更新的重要功能

  • 局部变量类型推断
  • 增强java.util.Locale
  • 提供了一组默认的根整数颁发机构(CA)

1.6 java9版本中更新的重要功能

  • 模块系统
  • 不可变的List、Set、Map的工厂方法
  • 接口中可以有私有方法
  • 垃圾收集器改进

1.5 java8版本中更新的重要功能

  • 函数式编程和Lambda表达式
  • Stream流
  • java Date Time API
  • 接口中可以使用默认方法和静态方法

2、java面向对象编程的特征

  • 抽象
  • 继承
  • 封装

PS:java不是纯粹的面向对象编程语言,因为java支持基本数据类型,比如int、short、long。尽管它们有自己的包装器类型,但是他们的确不能算是对象

3、 JVM

4、JDK、JVM、JRE区别

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ny3tV8aM-1598412721043)(https://gitee.com/iszhonghu/imagebed/raw/master/img/20200821104247.png)]

  • JDK:是提供给java开发人员的软件环境,包含JRE和一组开发工具;有几个版本:
    • 标准版
    • 企业版
    • 微型版
  • JRE:是JVM的实现,JRE是由JVM和Java二进制文件以及其他类组成,可以执行任何程序。JRE不包含Java编译器,调试器等任何开发工具

java编译器的任务是将java源代码转换为字节码,可以通过javac命令执行,因此它在JDK中,JRE不需要

5、java为什么不支持多重继承

防止出现菱形问题:ClassA和ClassB都继承了一个有特定方法的父类,该方法会被两个子类重写,当ClassC多重继承ClassA和ClassB时,不知道该调用那个重写方法。所以不支持多重继承

6、java重写(Overrider)和重载(Overload)有什么区别

  • 重写:重写的两个方法名相同,方法参数的个数也相同,不过是一个在父类中,一个在子类中。
    • 子类的异常不能超过父类
  • 重载:重载的两个方法名相同,但方法参数的个数不相同,另外也不涉及到继承,两个方法在同一个类中。
    • 与修饰符和返回值类型无关
    • 体现的是编译时的多态性

总结:

  • 编译器无法决定调用那个重写的方法,因为只从变量的类型上是无法判断的,要在运行时才能决定;单编辑器可以明确的知道该调用那个重载方法,因为引用类型是确定的,参数个数决定了该调用那个方法
  • 多态针对的是重写而不是重载

7、访问权限修饰符

目前一共有四种:public、private、protected、default(缺省)

一个类只能被public或者default修饰

8、abstract:抽象

  • abstract类不能实例化对象
  • abstract类可以不包含abstract方法,但是只要有一个abstract方法,那么该类必须为abstract类
  • abstract方法没有方法体,需要被override
  • abstract类的子类要么实现其父类全部的abstract方法,要么也是一个abstract类
  • abstract不能修饰属性
  • abstract不能修饰局部变量

9、static关键字:静态

  • **修饰成员变量和成员方法:**被 static 修饰的成员属于类,不属于单个这个类的某个对象,被类中所有对象共享,可以并且建议通过类名调用。被static 声明的成员变量属于静态成员变量,静态变量 存放在 Java 内存区域的方法区。
  • 静态代码块: 静态代码块定义在类中方法外, 静态代码块在非静态代码块之前执行(静态代码块—>非静态代码块—>构造方法)。 该类不管创建多少对象,静态代码块只执行一次.
  • 静态内部类(static修饰类的话只能修饰内部类): 静态内部类与非静态内部类之间存在一个最大的区别: 非静态内部类在编译完成之后会隐含地保存着一个引用,该引用是指向创建它的外围类,但是静态内部类却没有。没有这个引用就意味着:1. 它的创建是不需要依赖外围类的创建。2. 它不能使用任何外围类的非static成员变量和方法。
  • 静态导包(用来导入类中的静态资源,1.5之后的新特性): 格式为:import static 这两个关键字连用可以指定导入某个类中的指定静态资源,并且不需要使用类名调用类中静态成员,可以直接使用类中静态成员变量和成员方法。

PS:

  • static修饰的变量可以重写赋值
  • static方法中不能使用this和super关键字
  • static方法必须被实现,而不能是抽象的abstract
  • static方法只能被static方法覆盖

10、finally、finalize、final有什么区别

  • final:只赋值一次。表示最终的不可改变

    • 用于修饰类、方法和变量
    • 表示类不能继承,方法不能重写,成员变量必须要初始化
    • private类型的方法默认是final类型的
  • finally通常与try-catch块一起使用,即使try-catch块引发了异常,finally块中的代码也会被执行,用于释放try块中创建的资源

    PS:但是不一定会执行:在try前直接返回、抛出异常、系统退出

  • finalize()是Object类的一个特殊方法,当对象正在被垃圾回收时,垃圾收集器将会调用该方法。

11、抽象类和接口有什么区别

比较 抽象类 extends 接口 implements
默认方法 抽象类可以有默认的方法实现 java 8之前,接口中不存在方法的实现.
实现方式 子类使用extends关键字来继承抽象类.如果子类不是抽象类,子类需要提供抽象类中所声明方法的实现. 子类使用implements来实现接口,需要提供接口中所有声明的实现
构造器 抽象类中可以有构造器和构造方法 接口中不能有构造器和构造方法
和正常类区别 抽象类不能被实例化 接口则是完全不同的类型
访问修饰符 抽象方法可以有public,protected和default等修饰 接口默认是public,不能使用其他修饰符
多继承 一个子类只能存在一个父类 一个子类可以存在多个接口
添加新方法 向抽象类中添加新方法,可以提供默认的实现,因此可以不修改子类现有的代码 如果往接口中添加新方法,则子类中需要实现该方法.
构造函数和main方法 可以有 不能有
  • 抽象类中可以有普通成员变量;接口中没有普通成员变量。
  • 接口不能实现另外一个接口,但是可以继承一个接口

12、java反射

java反射机制是在运行状态中,对于任意一个类,都能知道这个类所有字段和方法;对于任意一个对象,都能调用它的任意字段和方法;这种动态获取信息以及动态调用对象方法的功能称为java反射机制

在常规编程中应该尽可能的避免,因为反射可以通过调用私有的构造方法来破坏设计模式,比如单例模式

但是也正因为反射的存在,出现了Spring之类的框架,甚至Tomcat之类的服务器,他们都通过反射调用适当的方法来对类实例化,省去了很多麻烦

13、java中的组合

通过对象组合可以实现代码的重用,java组合是通过引用其他对象的引用来实现的,使用组合的好处就是我们可以控制其他对象对使用者的可见性,并且可以重用我们需要的对象

14、组合和继承的优缺点

组合关系 继承关系
不破坏封装,整体类与局部类之间松耦合,彼此相对独立 破坏了封装关系,子类和父类紧密耦合,子类依赖父类的实现,子类缺乏独立性
具有较好的可扩展性 支持扩展,但是以增加系统结构的复杂度为代价
支持动态组合,在运行时,整体对象可以选择不同类型的局部对象 不支持动态扩展
整体类可以对局部类进行包装,封装局部类的接口,提供新接口 子类不能改变父类的接口
创建整体类的对象时,需要创建所有局部类的对象 创建子类的对象时,无需创建父类的对象
整体类不能自动获得和局部类同样的接口 子类能自动继承父类的接口

15、 java中的类加载器

当我们要访问任何类的时候,都需要通过java Classloader将该类的字节码加载到内存当中,可以通过继承ClassLoader并重写loadClass(String name)方法来创建自定义的类加载器

15.1 类加载器的种类

  • Bootstrap类加载器,用来加载JDK的内部类
  • Extensions类加载器,从JDK扩展目录(JAVA_HOME/lib/ext)中加载类
  • System类加载器,从当前类路径加载类

16、super与this关键字

16.1 super:表示父类的存储空间标识(父类的引用)

当在子类中重写了父类方法时,可以通过super关键字访问父类方法

也可以使用super关键字在子类构造方法中调用父类的构造方法,它必须是构造方法中的第一条语句

16.2 this:代表当前对象的引用(谁调用就代表谁)

this关键字提供对当前对象的引用,主要用于确保使用了当前对象的变量,而不是具有相同名称的局部变量

还可以使用this关键字在构造方法中调用其他构造方法

每次创建子类对象时,先初始化父类空间,再创建其子类对象本身。目的在于子类对象中包含了其对应的父类空间,便可以包含其父类的成员,如果父类成员非private修饰,则子类可以随意使用父类成员。代表体现在子类的构造方法调用时,一定先调用父类的构造方法

17、break和continue

break主要是用来终止for、while、do-while循环,也可以在switch语句中使用break来退出case条件

continue主要是用在or、while、do-while循环跳过当前迭代;甚至可以使用带有标签的continue语句来跳过最外层循环的当前迭代。

18、垃圾回收

垃圾回收,简称GC,会查看堆内存,识别正在使用和未使用的对象,以及会自动删除未使用的对象,用来释放内存

19、序列化和反序列化

我们可以把一个 Java 对象转化成一个数据流,这被称为序列化。一旦对象被转化为数据流后,就可以将其保存到文件或者通过网络套接字发送。

如果一个对象实现了 Serializable 接口,就可以使用 java.io.ObjectOutputStream 将对象写入文件。

将数据流再转化为 Java 对象被称为反序列化。

20、解释内存中栈(stack)、堆(heap)和静态存储区的用法

  • 栈空间:基本数据类型的变量、对象的引用、函数调用的线程保存
  • 堆空间:通过new关键字和构造器创建的对象
  • 静态存储区:程序中的字面量

Sting str = new String(“hello”);

str放在栈上,new出来的字符串对象放在堆上,而hello这个字面量放在静态存储区中

但是只创建了两个对象,一个是静态存储区中的“hello”,一个是用new创建在堆上的对象

21、java是值传递的

java中只有值传递,当一个对象实例作为一个参数被传递到方法中时,参数的值就是对该对象的引用。对象的属性可以在被调用的过程中改变,但对象的引用是永远不会改变的。

22、静态嵌套类和内部类的差别

  • 静态嵌套类是被声明为静态的内部类,它可以不依赖于外部类实例而被实例化
  • 内部类:需要在外部类实例化后才能实例化

23、==和equals的区别

  • ==:用来判断两个对象的地址是否相同,即是否指向相同的一个对象。比较的是真正意义上的指针操作。
  • equals:用来比较的是两个对象的内容是否相同,由于所有的类都是继承自object,所以适用于所有的对象,如果没有对该方法重新,object的equals方法等同于==

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

  • 包装类可以为null而基础类不可以。这使得包装类可以应用于POJO、DTO、VO、PO
  • 包装类型可以用于泛型,而基本类型不可以;因为泛型在编译是会进行类型擦除,最后只保留原始类型
  • 基本类型比包装类型更加高效:基本类型之间存储的具体数据,而包装类型则存储的是堆中的引用
  • 两个包装类型的值可以相等,但是却不相等

25、java八种基本数据类型

  • byte
  • short
  • char
  • int
  • long
  • float
  • double
  • boolean

26、java字符串类

  • String:不可变,最慢
    • final修饰,String类的方法都是放回新的String
    • 适用于少量的字符串操作
  • StringBuilder:可变、快
    • 适用于单线程下在字符串缓冲区进行大量操作
  • StringBuffer:线程安全
    • 适用于多线程下在字符串缓冲器进行大量操作

27、throw和throws的区别

  • throw:
    • 表示方法内抛出某种异常对象
    • 如果异常对象是非运行时错误,则需要在方法申明时加上该异常的抛出,即需要加上throws语句,或者在方法体内try-catch异常,否则编译报错
    • 执行到throw语句则后面的语句块不再执行
  • throws:
    • 方法在定义上使用throws表示这个方法可能抛出某种一床
    • 需要由方法的调用者进行异常处理

28、java程序从源代码到运行的步骤

.java文件通过JDK中的javac编译,编程.class文件,然后后由JVM变成机器可以执行的二进制机器码

29、对象克隆

  • 需求场景:方法需要return引用类型,但又不希望自己的对象被修改,程序之间方法的调用时参数的传递。有些场景为了保证引用类型的参数不被其他方法修改,可以使用克隆后的值作为参数传递
  • 实现:
    • 实现Cloneable接口,重写clone方法
  • 深拷贝和浅拷贝
    • 浅拷贝:复制基本类型的属性;引用类型的属性复制,复制栈中的变量 和 变量指向堆内存中的对象的指针,不复制堆内存中的对象
    • 深拷贝:复制基本类型的属性;引用类型的属性复制,复制栈中的变量 和 变量指向堆内存中的对象的指针和堆内存中的对象

30、hashcode()和equals()

  • hashcode():作用就是获取哈希码(散列值),实际上安徽的是一个int整型。这个哈希码的作用就是用来确定对象在哈希表中的索引位置

  • 相关规定

    • 如果两个对象相等,则hashcode一定相等
    • 两个对象相等,对两个对象分别调用equals方法都返回true
    • 两个对象有相同的hashcode值,但是不一定相等
    • equals方法被重写免责hashcode也必须被重写
    • hashcode的默认行为是对堆上的对象产生独特值。如果没有重写hashcode,则该class的两个对象无论如何都不会相等
  • 规范

    • 若重写 equals (Object obj) 方法,有必要重写 hashcode () 方法,确保通过 equals (Object obj) 方法判断结果为 true 的两个对象具备相等的 hashcode () 返回值。说得简单点就是:“如果两个对象相同,那么他们的 hashcode 应该 相等”。(注意不是强制)
    • 如果 equals (Object obj) 返回 false,即两个对象 “不相同”,并不要求对这两个对象调用 hashcode () 方法得到两个不相同的数。说的简单点就是:“如果两个对象不相同,他们的 hashcode 可能相同”。
  • 推论

    • 如果两个对象 equals,Java 运行时环境会认为他们的 hashcode 一定相等。
    • 如果两个对象不 equals,他们的 hashcode 有可能相等。
    • 如果两个对象 hashcode 相等,他们不一定 equals。
    • 如果两个对象 hashcode 不相等,他们一定不 equals。

    因为hashmap要求键值不能相同,java判断是否相等,先调用hashcode()判断hash值是否相同,再调用equal来判断

31、java创建对象的几种方式

  • 采用new
  • 通过反射
  • 采用clone
  • 通过序列化机制

32、java四种引用

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

  • 定义位置不同
    • 局部变量:在方法内部
    • 成员变量:在方法外部,直接写在类当中
  • 作用范围不一样
    • 局部变量:只有在方法当中才可以使用
    • 成员变量:整个类中通用
  • 默认值不一样
    • 局部变量:没有默认值,想使用必须手动赋值
    • 成员变量:如果没有赋值,就会有默认值
  • 内存位置不一样
    • 局部变量:位于栈内存
    • 成员变量:位于堆内存
  • 生命周期不一样
    • 局部变量:随着方法进栈而诞生,随着方法出栈而消失
    • 成员变量:随着对象创建而诞生,随着对象被垃圾回收而消失

34、JSON序列化

35、java异常处理

36、java集合

杂谈

  • instanceof关键字是用来检查对象是否属于同一个类
  • 静态方法可以用类的名称来调用,而不是用对象引用变量
  • 移位是最有效的计算2次方的操作
  • 构造器不能被继承因此不能被重写,但是可以重载

最后

  • 如果觉得看完有收获,希望能给我点个赞,这将会是我更新的最大动力,感谢各位的支持
  • 欢迎各位关注我的公众号【java冢狐】,专注于java和计算机基础知识,保证让你看完有所收获,不信你打我
  • 如果看完有不同的意见或者建议,欢迎多多评论一起交流。感谢各位的支持以及厚爱。

本文地址:https://blog.csdn.net/issunmingzhi/article/details/108236740