Java常见面试题(精选36道核心面试题)
目录
- 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、JDK、JVM、JRE区别
- 5、java为什么不支持多重继承
- 6、java重写(Overrider)和重载(Overload)有什么区别
- 7、访问权限修饰符
- 8、abstract:抽象
- 9、static关键字:静态
- 10、finally、finalize、final有什么区别
- 11、抽象类和接口有什么区别
- 12、java反射
- 13、java中的组合
- 14、组合和继承的优缺点
- 15、 java中的类加载器
- 16、super与this关键字
- 17、break和continue
- 18、垃圾回收
- 19、序列化和反序列化
- 20、解释内存中栈(stack)、堆(heap)和静态存储区的用法
- 21、java是值传递的
- 22、静态嵌套类和内部类的差别
- 23、==和equals的区别
- 24、基本类型和包装类型的区别
- 25、java八种基本数据类型
- 26、java字符串类
- 27、throw和throws的区别
- 28、java程序从源代码到运行的步骤
- 29、对象克隆
- 30、hashcode()和equals()
- 31、java创建对象的几种方式
- 32、[java四种引用](https://blog.csdn.net/issunmingzhi/article/details/104937017)
- 33、成员变量和局部变量的区别
- 34、[JSON序列化](https://blog.csdn.net/issunmingzhi/article/details/107468486)
- 35、[java异常处理](https://blog.csdn.net/issunmingzhi/article/details/105600956)
- 36、[java集合](https://blog.csdn.net/issunmingzhi/article/details/103489773)
- 杂谈
- 最后
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