随着互联网行业的不断发展,Java作为一种广泛应用的编程语言,依然在企业级应用开发中占据着重要地位。Java开发人员的需求量始终保持稳定,无论是前端、后端开发,还是全栈开发,Java程序员在各个领域中都扮演着重要角色。因此,Java程序员的面试成为了求职过程中至关重要的一环。
在面试过程中,考察技术能力的同时,也会考察编程思想、架构设计、解决问题的能力等多个方面。Java程序员面试问题范围广泛,涉及到Java基础、框架、并发、多线程、数据库、分布式等各个技术领域。本文将详细解析一些常见的面试问题,并给出解答与思路,帮助你更好地准备Java程序员面试。
一、基础概念
1.1 什么是 Java ?
Java 是一种广泛使用的计算机编程语言,由 Sun Microsystems 公司于 1995 年推出。它是一种面向对象的编程语言,可以编写各种类型的应用程序,包括 Web 应用程序、桌面应用程序、移动应用程序和企业应用程序等。
1.2 Java 语言有哪些特点?
Java 语言有以下几个主要特点:
-
简单易学:Java 语言的语法比较简单,易于学习和理解,有利于快速开发。
-
面向对象:Java 语言是一种面向对象的编程语言,它支持封装、继承和多态等面向对象的特性。
-
跨平台性:Java 语言具有跨平台性,可以在多种不同的计算机系统上运行,而不需要针对不同平台编写不同的代码,这是因为 Java 程序是通过编译器将源代码编译成字节码,然后在 JVM 上运行。
-
安全性:Java 语言具有较高的安全性,它通过类加载器、字节码校验器、安全管理器等多种机制来保证程序的安全性。
-
高性能:Java 语言具有较高的性能,虽然它是一种解释型语言,但通过 JIT 编译器和即时编译技术等优化手段,可以实现接近于本地代码的执行效率。
-
大量的类库和工具:Java 语言拥有丰富的类库和工具,包括标准类库、第三方类库和开发工具等,开发人员可以使用这些类库和工具来快速开发应用程序。
-
开放性:Java 语言具有开放性,它是一种开源的编程语言,拥有庞大的开发者社区和丰富的资源。
1.3 JDK 与 JRE 有什么区别?
-
JDK:Java 开发工具包(Java Development Kit),提供了 Java 的开发环境和运行环境。
-
JRE:Java 运行环境(Java Runtime Environment),提供了 Java 运行所需的环境。
-
JDK 包含了 JRE。如果只运行 Java 程序,安装 JRE 即可。要编写 Java 程序需安装 JDK.
二、Java基础语法
2.1 Java的基本数据类型有哪些?
Java的基本数据类型分为两类:原始数据类型和引用数据类型。原始数据类型包括:
-
整数类型:byte(1字节),short(2字节),int(4字节),long(8字节)
-
浮点类型:float(4字节),double(8字节)
-
字符类型:char(2字节)
-
布尔类型:boolean(1字节,值为true或false)
2.2 Java中final, finally, finalize的区别是什么?
-
final:用于修饰类、方法和变量。被修饰的类不可被继承,方法不可被重写,变量的值不可更改。
-
finally:用于异常处理,指的是无论异常是否发生,finally块中的代码都会执行。通常用于资源的清理工作,如关闭文件、数据库连接等。
-
finalize:是Object类中的一个方法,垃圾回收器在对象被回收之前调用此方法。通常在此方法中进行一些清理操作,如释放资源等。
2.3 Java中的对象和类的区别是什么?
-
类(Class) :类是对象的模板或蓝图,它定义了对象的属性和方法。
-
对象(Object) :对象是类的实例,是在程序运行时由类创建的实体。每个对象都拥有类定义的属性和方法。
2.4 什么是包装类?为什么需要包装类?
Java 中有 8 个基本类型,分别对应的 8 个包装类
-
byte -- Byte
-
boolean -- Boolean
-
short -- Short
-
char -- Character
-
int -- Integer
-
long -- Long
-
float -- Float
-
double -- Double
为什么需要包装类:
-
基本数据类型方便、简单、高效,但泛型不支持、集合元素不支持
-
不符合面向对象思维
-
包装类提供很多方法,方便使用,如 Integer 类 toHexString(int i)、parseInt(String s) 方法等等
2.5 equals 和 == 的区别
在 Java 中,== 运算符用于比较两个对象的引用是否指向同一内存地址,而 equals() 方法用于比较对象的实际内容。例如,对于字符串比较,若直接使用 ==,可能因字符串常量池的存在导致意外结果。正确的做法是使用 equals() 方法,以确保比较的是字符串的值。需要注意的是,自定义类如果没有重写 equals() 方法,则默认继承自 Object 类的实现,即仍然基于引用地址比较。因此,在需要比较对象逻辑相等性时,应正确重写 equals() 和 hashCode() 方法,以保证一致性。
2.6 简述 Java 访问修饰符
default: 默认访问修饰符,在同一包内可见
private: 在同一类内可见,不能修饰类
protected : 对同一包内的类和所有子类可见,不能修饰类
public: 对所有类可见
2.7 简述自动装箱拆箱
对于 Java 基本数据类型,均对应一个包装类。
装箱就是自动将基本数据类型转换为包装器类型,如 int->Integer
拆箱就是自动将包装器类型转换为基本数据类型,如 Integer->int
三、Java面向对象
3.1 Java的继承和多态机制是什么?
-
继承:Java允许子类继承父类的属性和方法,从而实现代码的复用。使用关键字
extends声明继承关系。 -
多态:多态是指同一方法调用可以根据不同对象的不同实现产生不同的行为。Java实现多态有两种方式:方法重载(编译时多态)和方法重写(运行时多态)。
3.2 抽象类与接口的区别?
-
抽象类:可以包含抽象方法和已实现的方法。抽象类可以有构造方法,但不能被实例化。子类继承抽象类时,必须实现其中的抽象方法(除非子类也是抽象类)。
-
接口:接口只包含抽象方法(Java 8以后也可以有默认方法和静态方法)。类实现接口时,必须实现接口中的所有方法。接口支持多继承。
3.3 创建对象有哪些方式
有五种创建对象的方式
-
1、new关键字
Person p1 = new Person();
-
2.Class.newInstance
Person p1 = Person.class.newInstance();
-
3.Constructor.newInstance
Constructor<Person> constructor = Person.class.getConstructor();
Person p1 = constructor.newInstance();
-
4.clone
Person p1 = new Person();
Person p2 = p1.clone();
-
5.反序列化
Person p1 = new Person();
byte[] bytes = SerializationUtils.serialize(p1);
Person p2 = (Person)SerializationUtils.deserialize(bytes);
3.4 简述 Object 类常用方法
-
hashCode:通过对象计算出的散列码。用于 map 型或 equals 方法。需要保证同一个对象多次调用该方法,总返回相同的整型值。
-
equals:判断两个对象是否一致。需保证 equals 方法相同对应的对象 hashCode 也相同。
-
toString: 用字符串表示该对象
-
clone:深拷贝一个对象
3.5 一个对象的内存布局是怎么样的?
-
1.对象头: 对象头又分为 MarkWord 和 Class Pointer 两部分。
-
MarkWord:包含一系列的标记位,比如轻量级锁的标记位,偏向锁标记位,gc记录信息等等。
-
ClassPointer:用来指向对象对应的 Class 对象(其对应的元数据对象)的内存地址。在 32 位系统占 4 字节,在 64 位系统中占 8 字节。
-
-
2.Length:只在数组对象中存在,用来记录数组的长度,占用 4 字节
-
3.Instance data: 对象实际数据,对象实际数据包括了对象的所有成员变量,其大小由各个成员变量的大小决定。(这里不包括静态成员变量,因为其是在方法区维护的)
-
4.Padding:Java 对象占用空间是 8 字节对齐的,即所有 Java 对象占用 bytes 数必须是 8 的倍数,是因为当我们从磁盘中取一个数据时,不会说我想取一个字节就是一个字节,都是按照一块儿一块儿来取的,这一块大小是 8 个字节,所以为了完整,padding 的作用就是补充字节,保证对象是 8 字节的整数倍。
四、Java集合框架
4.1 Java集合框架的主要接口有哪些?
Java集合框架主要分为两大类:Collection和Map。
-
Collection:List(如ArrayList,LinkedList),Set(如HashSet,TreeSet),Queue(如LinkedList,PriorityQueue)
-
Map:HashMap,TreeMap,LinkedHashMap,Hashtable
4.2 ArrayList和LinkedList的区别?
-
ArrayList:基于动态数组实现,适合随机访问,查询速度快,但在数组中间插入和删除元素时性能较差(O(n))。
-
LinkedList:基于双向链表实现,插入和删除操作效率高,适合做队列和栈,但查询效率较低(O(n))。
4.3 hashMap 1.7 和 hashMap 1.8 的区别?
重点区别
|
不同点 |
hashMap 1.7 |
hashMap 1.8 |
|---|---|---|
|
数据结构 |
数组+链表 |
数组+链表+红黑树 |
|
插入数据的方式 |
头插法 |
尾插法 |
|
hash 值计算方式 |
9次扰动处理(4次位运算+5次异或) |
2次扰动处理(1次位运算+1次异或) |
|
扩容策略 |
插入前扩容 |
插入后扩容 |
4.4 HashMap的底层数据结构是什么?
JDK 7 中,HashMap 由“数组+链表”组成,数组是 HashMap 的主体,链表则是主要为了解决哈希冲突而存在的。
在 JDK 8 中,HashMap 由“数组+链表+红黑树”组成。链表过长,会严重影响 HashMap 的性能,而红黑树搜索的时间复杂度是 O(logn),而链表是糟糕的 O(n)。因此,JDK 8 对数据结构做了进一步的优化,引入了红黑树,链表和红黑树在达到一定条件会进行转换:
-
当链表超过 8 且数据总量超过 64 时会转红黑树。
-
将链表转换成红黑树前会判断,如果当前数组的长度小于 64,那么会选择先进行数组扩容,而不是转换为红黑树,以减少搜索时间。
链表长度超过 8 体现在 putVal 方法中的这段代码:
//链表长度大于8转换为红黑树进行处理
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);
table 长度为 64 体现在 treeifyBin 方法中的这段代码::
final void treeifyBin(Node<K,V>[] tab, int hash) {
int n, index; Node<K,V> e;
if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY)
resize();
}
MIN_TREEIFY_CAPACITY 的值正好为 64。
static final int MIN_TREEIFY_CAPACITY = 64;
843

被折叠的 条评论
为什么被折叠?



