2021年Java面试题全集(含答案)
2021年Java面试题全集(含答案)已经引来了金三银四,企业招聘已经陆续开始了,小编在这关键时刻为你汇总Java面试题,有了小编的面试法宝让你参加Java面试更轻松。
一、Java基础
1、java中 == 和equals() 和 hashCode() 的区别
(1)、== 是运算符,a == b 比较的是 a,b的数值是否相等。
(2)、equals 是 Object 类的一个方法,默认情况下比较两个对象是否是同一个对象,内部的实现是通过 == 来比较两个对象的内存地址是否相等,其源码如下
1 public boolean equals(Object obj) {2 return (this == obj);3 }
如果想比较两个对象的其他内容,则可以通过重写 equals方法,例如 String 类就重写了 equals 方法,改成了对象的内容是否相等。
(3)、hashCode 也是Object 类的一个方法,返回值是该对象的哈希码,同一个对象的哈希码一定相等,但不同对象的哈希码也是有可能相等的。
(4)、hashCode() 与 equals() 的关系:如果两个对象根据 equals() 方法比较相等,那么这两个对象的 hashCode() 返回值一定相等;如果两个对象根据 equals() 方法比较不相等,那么这两个对象的 hashCode() 返回值不一定不相等
2、int与integer的区别
int 是一个基本数值类型,Integer 是一个对象,Integer 是 int 的一个包装类型,两者可以通过拆箱和装箱自动转换。
拓展一下:
1Integer a, b;
对于 a == b,比较的是 a 与 b 是否是同一个对象,但是如果运算符 == 左右两边算术运算的话,则 a,b会自动拆箱成 int 类型来进行比较。
二、JVM
1、什么情况下会触发类的初始化?
(1)、遇到 new, getstatic, putstatic, invokestatic 这4条字节码指令。
(2)、使用 java.lang.reflect 包的方法对类进行反射调用。
(3)、初始化一个类的时候,如果发现其父类还没有进行过初始化,则先初始化其父类(注意:
如果是接口的话,则不要求初始化父类)。
(4)、当虚拟机启动时,用户需要指定一个要执行的主类(包含 main()方法的那个类),虚拟机会先初始化这个主类。
(5)、当使用JDK 1.7 的动态语言支持时,如果一个 java.lang.invoke.MethodHandle 实例最后的解析结果 REF_getstatic, REF_putstatic, REF_invokeStatic的方法句柄,并且这个方法句柄所对应的类没有进行过初始化,则先触发其初始化。
外加几种不会初始化的例子:
(1)、同类子类引用父类的静态字段,不会导致子类初始化。至于是否会触发子类的加载和验证,则取决于虚拟机的具体实现。
(2)、通过数组定义来引用类,也不会触发类的初始化。例如下面这个语句:
1Animal[] a = new Animao[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}
运行结果是
动物跑啊跑
动物跑啊跑
相信大家学过重载的都能猜到是这个结果。但是,为什么会选择这个方法进行重载呢?虚拟机是如何选择的呢?
在此之前我们先来了解两个概念。
先来看一行代码:
Animal dog = new Dog();
对于这一行代码,我们把Animal称之为变量dog的静态类型,而后面的Dog称为变量dog的实际类型。
现在我们再来看看虚拟机是根据什么来重载选择哪个方法的。
对于静态类型相同,但实际类型不同的变量,虚拟机在重载的时候是根据参数的静态类型而不是实际类型作为判断选择的。并且静态类型在编译器就是已知的了,这也代表在编译阶段,就已经决定好了选择哪一个重载方法。
由于dog和lion的静态类型都是Animal,所以选择了run(Animal animal)这个方法。
静态分派的典型应用就是方法的重载的,现在应该知道什么是静态分派了吧?
动态分派
和静态分派类似,所谓动态分派就是就是根据方法的实际类型来选择调用哪个方法,而实际类型是需要到达运行期才能知道。像重写就是动态分派的典型应用了。
更多的详情可以看我之前写的一篇文章从jvm角度看懂类初始化、方法重载、重写。
3、如何⾃定义⼀个类加载器?你使⽤过哪些或者你在什么场景下需要⼀个⾃定义的类加载器吗?
可以把自己自定义的类加载器继承 ClassLoader,然后重写 findClass() 方法,把自己的类加载逻辑写到 findClass() 方法中去。
使用类加载器的场景:
加载特定路径的 class 文件
热部署加载 class 文件
从网络中加载一个加密的 class 文件
三、Java面试题(二):你真的懂这几道题了吗?
1、能否创建一个包含可变对象的不可变对象?
虽然很多人听说过不可变对象,但你不一定懂,以及知道怎么创建。
不可变对象:不可变对象(Immutable Objects)即对象一旦被创建它的状态(对象的数据,也即对象属性值)就不能改变,任何对它的改变都应该产生一个新的对象
如何创建不可变类?
可以遵照以下几点来编写一个不可变类:
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<Integer> list = new ArrayList<>();2 list.add(1);3 list.add(2);4 System.out.println(list.toString());
打印结果
1[1, 2]
list 所执行的对象还是可以改变滴,只是这个变量本身不能在被赋值,所以我们也经常把被 final 修饰的变量称之为常量。
【免责声明】本文部分系转载,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责,如涉及作品内容、版权和其它问题,请在30日内与我们联系,我们会予以重改或删除相关文章,以保证您的权益!
Java开发高端课程免费试学
大咖讲师+项目实战全面提升你的职场竞争力
- 海量实战教程
- 1V1答疑解惑
- 行业动态分析
- 大神学习路径图
相关推荐
更多2016-06-07
2016-06-15
2022-05-31
达内就业喜报
更多>Java开班时间
-
北京 丨 11月27日
火速抢座 -
上海 丨 11月27日
火速抢座 -
广州 丨 11月27日
火速抢座 -
兰州 丨 11月27日
火速抢座 -
杭州 丨 11月27日
火速抢座 -
南京 丨 11月27日
火速抢座 -
沈阳 丨 11月27日
火速抢座 -
大连 丨 11月27日
火速抢座 -
长春 丨 11月27日
火速抢座 -
哈尔滨 丨 11月27日
火速抢座 -
济南 丨 11月27日
火速抢座 -
青岛 丨 11月27日
火速抢座 -
烟台 丨 11月27日
火速抢座 -
西安 丨 11月27日
火速抢座 -
天津 丨 11月27日
火速抢座 -
石家庄 丨 11月27日
火速抢座 -
保定 丨 11月27日
火速抢座 -
郑州 丨 11月27日
火速抢座 -
合肥 丨 11月27日
火速抢座 -
太原 丨 11月27日
火速抢座 -
苏州 丨 11月27日
火速抢座 -
武汉 丨 11月27日
火速抢座 -
成都 丨 11月27日
火速抢座 -
重庆 丨 11月27日
火速抢座 -
厦门 丨 11月27日
火速抢座 -
福州 丨 11月27日
火速抢座 -
珠海 丨 11月27日
火速抢座 -
南宁 丨 11月27日
火速抢座 -
东莞 丨 11月27日
火速抢座 -
贵阳 丨 11月27日
火速抢座 -
昆明 丨 11月27日
火速抢座 -
洛阳 丨 11月27日
火速抢座 -
临沂 丨 11月27日
火速抢座 -
潍坊 丨 11月27日
火速抢座 -
运城 丨 11月27日
火速抢座 -
呼和浩特丨11月27日
火速抢座 -
长沙 丨 11月27日
火速抢座 -
南昌 丨 11月27日
火速抢座 -
宁波 丨 11月27日
火速抢座 -
深圳 丨 11月27日
火速抢座 -
大庆 丨 11月27日
火速抢座