当前位置: 首页 > 图灵资讯 > java面试题> 【java面试题】2021年Java面试题全集(含答案)

【java面试题】2021年Java面试题全集(含答案)

来源:图灵教育
时间:2021-12-03 13:21:39

  2021年java面试题全集(含答案)吸引了金三银四,企业招聘也陆续开始。小编在这个关键时刻总结了Java面试题。有了小编的面试法宝,你更容易参加Java面试。

  一、java基础

  1.java==与equals()和hashCode()的区别。

  (1)==是运算符,a==b比较a,b值是否相等。

  (2).equals是Object类的一种方法。默认情况下,比较两个对象是否相同,内部实现是通过==比较两个对象的内存地址是否相等,源代码如下。

  1publicboleanequals(objectobj){2return(this=obj)

  如果您想比较两个对象的其他内容,您可以重写equals方法,例如,string类重写equals方法,并将其改为对象的内容是否相等。

  (3).hashcode也是Object类的一种方法,返回值是对象的哈希码,同一对象的哈希码必须相等,但不同对象的哈希码也可能相等。

  (4).hashcode()与equals()的关系:如果两个对象按照equals()的方法相等,那么两个对象的hashcode()的返回值必须相等;如果两个对象按照equals()的方法不相等,那么这两个对象的hashcode()返回值可能不相等。

  2.int和integer的区别。

  int是一种基本的数值类型,integer是一种对象,integer是int的包装类型,可以通过拆卸和包装自动转换。

  拓展一下:

  1Integera,b;

  对于a==b,比较a和b是否是同一对象,但如果操作符==左右算术操作,a和b将自动拆箱成int类型进行比较。

  二.JVM

  1.在什么情况下触发类的初始化?

  (1).遇到new、getstatic、putstatic、invokestatic四个字节码指令。

  (2)使用java.lang.reflect包对类进行反射调用。

  (3).初始化一个类时,如果发现其父类还没有初始化,则先初始化其父类(注:

  如果是接口,则不需要初始化父类)。

  (4).当虚拟机启动时,用户需要指定要执行的主类(包括main()方法),虚拟机会首先初始化。

  (5).使用JDK1.7的动态语言支持时,如果一个java.lang.invoke.methodhandle实例的最终分析结果是REF_getstatic、REF_putstatic、REF_invokestatic的方法句柄,该方法句柄对应的类别没有初始化。

  加上几个不会初始化的例子:

  (1)同类子类引用父类静态字段,不会导致子类初始化。是否会触发子类的加载和验证,取决于虚拟机的具体实现。

  (2)通过数组定义引用类,不会触发类的初始化。例如,以下句子:

  Animal[]a=newanimao[10]

  Animal类的初始化不会触发。

  (3)引用一个类的常量不会触发初始化。

  2.谈谈你对分析和分配的理解。

  1.该方法在程序真正运行前有一个确定的调用版本,该方法的调用版本在运行过程中是不可变的,即编译时可以知道,运行不能改变。这种目标方法的调用称为分析。

  Java语言中符合编译器可知,运行期不变要求的方法主要包括静态方法和私有方法。

  2.分析调用必须是一个静态过程,在编译期内完全确定。在类加载的分析阶段,所有涉及的符号引用将转换为可确定的直接引用,不会延迟到运行期。而分配(Dispatch)调用可能是静态或动态的。因此,有静态分配和动态分配。

  下面我来解释一下静态分配和动态分配。

静态分派

看下面这段程序

  1//定义几个类 2 3public abstract class Animal { 4 } 5class Dog extends Animal{ 6 } 7class Lion extends Animal{ 8 } 910class Test4{ 11 public void run(Animal animal){12 System.out.println("动物跑啊跑");13 }14 public void run(Dog dog){15 System.out.println("小狗跑啊跑");16 }17 public void run(Lion lion){18 System.out.println("狮子跑啊跑");19 } 20 //测试21 public static void main(String[] args){22 Animal dog = new Dog();23 Animal lion = new Lion();;24 Test4 test4 = ew Test4();25 test4.run(dog);26 test4.run(lion);27 }28}

  运行结果是

  动物跑啊跑

  动物跑啊跑我相信每个学过重载的人都能猜到这是结果。但是,为什么要选择这种重载方法呢?如何选择虚拟机?

  在此之前,让我们先了解两个概念。

  先看一行代码:

  Animaldog=newdog();

  对于这一行代码,我们称Animal为变量dog的静态类型,而后面的Dog则称为变量dog的实际类型。

  现在让我们来看看虚拟机是如何重载的。

  对于静态类型相同但实际类型不同的变量,虚拟机根据参数的静态类型而不是实际类型进行选择。而且在编译器中已知了静态类型,这也意味着在编译阶段,已经决定了选择哪种重载方法。

  因为dog和lion的静态类型都是Animal,所以选择了run(Animalanimal)。

  静态分配的典型应用是方法的重载。现在我们应该知道什么是静态分配?

  动态分派

  类似于静态分布,所谓动态分布,就是根据方法的实际类型选择调用哪种方法,实际类型需要到达运行期才能知道。像重写是动态分布的典型应用。

  详见我之前写的一篇文章,从jvm的角度看类初始化。方法重载。

  3、如何⾃定义⼀个类加载器?你使⽤过哪些或者你在什么场景下需要⼀个⾃定义的类加载器吗?

  您可以继承自定义的类加载器Clasloader,然后重写findClass()方法,并将您的类加载逻辑写入findClass()方法。

  使用类加载器的场景:

  class文件加载特定路径。

  加载class文件进行热部署。

  加密class文件从网络中加载。

  Java面试题(2):你真的懂这些题吗?

  1.能否创建包含可变对象的不可变对象?

  虽然很多人都听说过不可改变的对象,但你可能不知道如何创建它们。

  不可变对象:不可变对象(Immutable)。

  即对象一旦被创建它的状态(对象的数据,也即对象属性值)就不能改变,任何对它的改变都应该产生一个新的对象

  如何创建不可变类?

  可以遵照以下几点来编写一个不可变类:

  A. 确保类不能被继承:将类声明为final, 或者使用静态工厂并声明构造器为private。。

  B. 确保对象的属性不能被修改:可以使用private和final修饰符来修饰该类的属性,以确保不被修改。

  C. 不要提供任何可以修改对象状态的方法。

  不过,如果对象的属性是一个可变对象,则需要特别注意,例如对于下面这个:

  1public final class ImmutableDemo { 2 private final int[] myArray; 3 public ImmutableDemo(int[] array) { 4 this.myArray = array; // 错了 5 } 6}

  虽然属性声明为 final 了,但是 array 是一个引用,别人是可以在外部改变这个数组的值的,进而 myArray 所指向的对象就被改变了。

  因为,如果属性是一个可变对象,我们应该采用克隆的方式。如下:

  1public final class MyImmutableDemo { 2 private final int[] myArray; 3 public MyImmutableDemo(int[] array) { 4 this.myArray = array.clone(); 5 } 6}

  不过,最好是采用深度克隆比较好。

问题的答案

  说了这么多,相信你也知道这道题的答案了,答是可以包含可变对象的,只是,我们要保证这个对象的状态不能被改变。

2. 谈谈对java多态的理解

  多态的功能:允许不同类对象对同一消息做出响应,即同一消息可以根据发送对象的实际类型的不同而调用不同的方法。

  这种根据实际类型来调用不可方法的技术也称之为动态绑定。

  多态其中的一个应用该就是方法的重写了。关于方法的重写,如果想更加深入了解可以看我这篇文章:从jvm角度看懂类初始化、方法重载、重写。

多态的一些优点总结:

可替换性

  :多态对已存在代码具有可替换性

可扩充性

  :增加新的子类不影响已经存在的类结构

接口性

  :多态是超类通过方法签名,向子类提供一个公共接口,由子类来完善或者重写它来实现的。

灵活性

简化性

  说实话,这些优点我是直接去抄过来的,看着好死,哈哈。

3. 5、final,finally,finalize的区别

  1、final 可以用来修改类、方法、变量。被 final 修改的类不可以被继承,变量不可以修改,方法则不可以重写。

  2、finally 则是 Java 保证重点代码一定要被执行的一种机制。例如我们可以用 try-finally 或者 try-catch-finally 类进行文件的关闭、JDBC的关闭等。

  3、finalize 是 Object 的一个方法,它会在对象被回收之前被调用。我们可以用这个方法等对象要被回收的时候,来完成一些特定的任务。不过需要注意的是,finalize 机制已经不推荐使用了,并且在 JDK9 开始被标记为 deprecated 了。

  拓展

a. 对于下面这段代码

  1 try {2 System.exit(1);3 }finally {4 System.out.println("猜一下我会不会执行");5 }

  你觉得 finally 里面的代码会被执行吗?

  答是不会的,因为System.exit(1)表达程序非正常退出,注意,非正常,也就是说,执行了这个语句,程序就要退出了。

b. 注意,被 final 修饰的变量,只是值这个变量不能在被赋值了,变量所指向的对象还是可以改变的。例如:

  1 final List list = new ArrayList<>();2 list.add(1);3 list.add(2);4 System.out.println(list.toString());

  打印结果

  1[1, 2]

  list 所执行的对象还是可以改变滴,只是这个变量本身不能在被赋值,所以我们也经常把被 final 修饰的变量称之为常量。