面试 Java 基础八股文十问十答第二十二期
作者:程序员小白条,个人博客
相信看了本文后,对你的面试是有一定帮助的!关注专栏后就能收到持续更新!
⭐点赞⭐收藏⭐不迷路!⭐
1)ArrayList和LinkedList的区别:
-
数据结构:
- ArrayList基于数组实现,内部以动态数组的形式存储元素,支持随机访问。
- LinkedList基于链表实现,每个元素都包含对前后元素的引用,不支持随机访问,但在插入和删除操作上效率更高。
-
访问效率:
- ArrayList支持通过索引进行快速访问,时间复杂度为O(1)。
- LinkedList需要从头部或尾部开始遍历链表以查找指定位置的元素,时间复杂度为O(n)。
-
插入和删除操作:
- 在ArrayList中,插入和删除元素时可能需要移动其他元素,因此效率较低,时间复杂度为O(n)。
- 在LinkedList中,插入和删除元素时只需修改相邻元素的指针,效率较高,时间复杂度为O(1)。
-
内存占用:
- ArrayList需要预先分配一定大小的内存空间,可能会造成内存浪费。
- LinkedList在每个元素中存储指向前后元素的引用,可能会占用更多的内存空间。
2)HashMap和HashTable的区别:
-
线程安全性:
- HashMap是非线程安全的,不支持多线程并发操作,需要外部进行同步处理。
- HashTable是线程安全的,内部的方法都经过同步处理,可以直接用于多线程环境。
-
性能:
- HashMap相对于HashTable,在无需考虑线程安全的情况下性能更好。因为HashTable的所有方法都是同步的,会在多线程情况下带来性能损失。
-
null键和null值:
- HashMap允许键和值都为null,且允许多个键为null的entry。
- HashTable不允许键和值为null,否则会抛出NullPointerException。
-
继承关系:
- HashMap继承自AbstractMap类,实现了Map接口。
- HashTable继承自Dictionary类,实现了Map接口,并且是Hashtable的子类。
3)Collection包结构,与Collections的区别:
-
Collection包结构:
- Collection是Java集合框架的顶层接口,定义了一组集合的基本操作和行为。
- Collection包括List、Set和Queue这三种主要的集合类型。
-
Collections工具类:
- Collections是Java提供的一个工具类,提供了一系列静态方法,用于操作各种集合。
- Collections包括对集合进行排序、查找、同步化等常见操作的方法。
-
区别:
- Collection是Java集合框架的一部分,定义了集合的基本行为和操作,是所有集合类的根接口。
- Collections是一个工具类,提供了一系列静态方法,用于对集合进行操作和处理,如排序、查找、同步化等。
4)Java的四种引用:
-
强引用(Strong Reference):
- 强引用是指在程序中普遍存在的引用,即通过new关键字创建的对象的默认引用类型。
- 只有当没有任何强引用指向一个对象时,该对象才会被垃圾回收器回收。
-
软引用(Soft Reference):
- 软引用用于描述一些还有用但非必须的对象。
- 当系统内存不足时,垃圾回收器会根据软引用的情况来决定是否回收这部分对象,从而避免OutOfMemoryError的发生。
-
弱引用(Weak Reference):
- 弱引用是一种比软引用更弱的引用类型。
- 即使有弱引用指向一个对象,只要垃圾回收器运行时,不论内存是否足够,该对象都会被回收。
-
虚引用(Phantom Reference):
- 虚引用是最弱的一种引用类型。
- 它不能单独使用,必须和引用队列(ReferenceQueue)一起使用。
- 当虚引用指向的对象被垃圾回收器回收时,会将虚引用插入到引用队列中。
5)泛型常用特点:
- 类型安全:泛型提供了编译时类型检查机制,可以在编译阶段捕获到类型不匹配的错误,从而提高了代码的安全性。
- 代码复用:通过泛型,可以编写出更加通用、灵活的代码,减少代码的重复编写,提高代码的可复用性。
- 减少类型转换:使用泛型可以避免手动进行类型转换,使代码更加清晰简洁。
- 提高性能:由于泛型在编译时进行类型检查,避免了运行时的类型转换,因此可以提高程序的性能。
6)Java创建对象有几种方式?
Java中创建对象的方式主要有以下几种:
-
使用new关键字:使用
new
关键字直接调用类的构造函数来创建对象,例如:MyClass obj = new MyClass();
- 使用反射机制:通过Class类的newInstance()方法或Constructor类的newInstance()方法来动态创建对象。
Class<?> clazz = Class.forName("com.example.MyClass");
MyClass obj = (MyClass) clazz.newInstance();
- 使用clone()方法:在类中实现Cloneable接口并重写clone()方法,然后通过调用clone()方法来复制对象。
MyClass obj1 = new MyClass();
MyClass obj2 = (MyClass) obj1.clone();
- 使用对象序列化:将对象转换成字节流,并保存到文件或在网络中传输,然后再从字节流中反序列化出对象。
// 将对象序列化到文件
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("object.ser"));
out.writeObject(obj);
out.close();
// 从文件中反序列化对象
ObjectInputStream in = new ObjectInputStream(new FileInputStream("object.ser"));
MyClass newObj = (MyClass) in.readObject();
in.close();
- 使用工厂方法:通过工厂方法创建对象,可以根据不同的参数返回不同类的实例。
public class MyClassFactory {
public static MyClass createObject() {
return new MyClass();
}
}
MyClass obj = MyClassFactory.createObject();
7)有没有可能两个不相等的对象有相同的hashCode
?
是的,这是可能的。根据哈希算法的设计,不同的对象可能会生成相同的哈希码。这种情况称为哈希冲突。哈希冲突的出现是正常的,而哈希算法的目标是尽量减少冲突的概率。在哈希表中,一般会使用一种解决冲突的方法,比如链地址法或开放寻址法。
8)深拷贝和浅拷贝的区别是什么?
- 浅拷贝(Shallow Copy):浅拷贝会创建一个新对象,然后将原对象的非静态字段的值复制到新对象中。如果字段是基本类型,则拷贝其值;如果字段是引用类型,则拷贝引用而不是对象本身。因此,原对象和浅拷贝对象中的引用类型字段仍然指向相同的对象。
- 深拷贝(Deep Copy):深拷贝会创建一个新对象,并递归地将原对象及其所有引用的对象的字段都复制到新对象中。这样,原对象和深拷贝对象中的所有引用类型字段都指向不同的对象,彼此之间互不影响。
简而言之,区别在于是否复制引用对象本身以及引用对象内部的所有对象。
9)final
有哪些用法?
final
关键字在Java中有多种用法:
-
修饰变量:用于声明一个常量,一旦赋值就不能修改。
final int NUM = 10;
-
修饰方法:用于声明方法不能被子类重写。
public final void method() { // 方法体 }
-
修饰类:用于声明类不能被继承。
public final class MyClass { // 类体 }
-
修饰成员变量:用于在多线程环境下保证线程安全。
private final Object lock = new Object();
10)static
都有哪些用法?
static
关键字在Java中有以下主要用法:
-
静态变量(类变量):用于声明类的静态变量,所有对象共享该变量的内存空间。
public static int count;
-
静态方法:用于声明类的静态方法,可以直接通过类名调用,无需实例化对象。
public static void print() { // 方法体 }
-
静态代码块:用于在类加载时执行一次性的初始化操作。
static { // 静态代码块的初始化操作 }
-
静态内部类:用于声明一个嵌套在外部类中的静态内部类。
public class OuterClass { static class StaticInnerClass { // 静态内部类的成员 } }
-
静态导入:用于直接导入静态成员,可以使代码更简洁。
import static java.lang.Math.PI;
-
静态常量:用于声明不可改变的常量。
public static final double PI = 3.14159;
开源项目地址:https://gitee.com/falle22222n-leaves/vue_-book-manage-system
前后端总计已经 900+ Star,1.5W+ 访问!
⭐点赞⭐收藏⭐不迷路!⭐