Hi,大家好,我是王二蛋。
金三银四求职季,特地为大家整理出13个 Java 基础面试题,希望能为正在准备或即将参与面试的小伙伴们提供些许帮助。
后续还会整理关于线程、IO、JUC等Java相关面试题,敬请各位持续关注。
这13个基础面试题先给大家罗列出来
1.Java 创建对象有几种方式?
在Java中,创建对象主要有以下几种方式:
-
使用new关键字创建对象:这是最常见和直接的方式。通过调用类的构造函数,可以使用new关键字创建对象。
-
使用Class类的newInstance方法:如果类有一个无参数的公共构造函数,可以使用Class对象的newInstance方法创建对象。
-
使用反序列化创建对象:当从文件、网络或其他IO流中读取对象的序列化表示时,可以使用Java的对象反序列化来创建对象。这通常涉及到ObjectInputStream类。
-
使用克隆方法创建对象:如果类实现了Cloneable接口并覆盖了Object类的clone方法,那么可以通过调用对象的clone方法来创建该对象的一个副本。
-
使用工厂方法创建对象:工厂方法是一种设计模式,它封装了对象的创建逻辑,并返回该类型的对象。
-
使用依赖注入框架创建对象:在大型项目中,通常使用如Spring这样的依赖注入框架来创建和管理对象。
2.有了数组为什么还要ArrayList?
为了方便程序员!!!
数组的大小在创建时是固定的,一旦创建,其大小就不能改变。如果要添加更多的元素,就需要创建一个新的更大的数组,并将旧数组的元素复制到新数组中。ArrayList 提供了add(), remove(), get(), size()等方法可以帮助程序员完成这一切工作,更灵活、更便利。
3.重载和重写的区别
重载发生在一个类中。同一个方法名如果有不同的参数列表(参数类型、个数、顺序不同)则视为重载,是多态的一种表现。
重写发生在父类与子类之间。现象就是在子类中把父类本身有的方法重新写一遍。
如果父类中的某个方法不满足子类的需求,子类就可以在方法名、参数列表、返回类型都相同的情况下,对方法体进行重写。
4.什么是内部类?应用在什么场景?
在一个类或者一个方法里面定义的类,称为内部类。
根据它们被定义的位置和方式,内部类可以分为四种类型:成员内部类、静态内部类、局部内部类和匿名内部类。
成员内部类
成员内部类定义在类的成员位置,可以访问外部类的所有成员。
通常被用于封装和组合,比如一对一关系的声明。
静态内部类
静态内部类是static修饰的成员内部类,可以直接访问外部类的所有静态成员。
通常用于实现与外部类关联但不依赖于外部类实例的工具类、单例模式或工厂模式等。
局部内部类
局部内部类定义在方法、构造器或初始化块中。它只能访问外部类的final成员,以及它所在方法或构造器的final局部变量。
通常用于提供临时的功能。
匿名内部类
匿名内部类通常是一个接口的实现类对象,它主要用于简化代码和提供临时的实现。
经常使用匿名内部类来实现Runnable接口
5.介绍下Java中的四种引用
强引用
强引用是默认的引用类型,当一个对象具有强引用时,垃圾回收器不会回收该对象,即使系统内存不足也不会回收。
强引用通常用于确保对象一直存在,例如在单例模式或缓存中。
软引用
软引用是一种比较灵活的引用类型。在系统内存足够时,软引用的对象不会被垃圾回收器回收。但当内存空间不足时,这些对象就会被回收。
软引用主要用于实现内存缓存。
弱引用
弱引用比软引用更弱一些。无论当前内存空间足够与否,只要JVM开始进行垃圾回收,被弱引用关联的对象必定会被回收。
虚引用
虚引用是Java中最弱的一种引用类型,它并不会决定对象的生命周期。
虚引用主要用于跟踪对象被垃圾回收的情况,例如NIO中的DirectByteBuffer等。通过虚引用,我们可以获取到一个对象是否已经被垃圾回收了。
6.static都有哪些用法?
在Java中,static是一个关键字,用于声明属性和方法成员方法,以及内部类。
静态变量
静态变量是类级别的变量,它不属于任何对象实例。静态变量在类加载时初始化,并且只有一个副本存在于内存中,不管创建了多少个对象。所有的对象实例共享同一个静态变量的值。
静态方法
静态方法也是类级别的,不依赖于任何对象实例。静态方法只能访问静态成员变量或调用其他静态方法,因为它们没有与任何对象实例关联。
静态块
静态块是在类加载时执行的代码块。它们通常用于初始化静态变量或只需要执行一次的类级别的操作。
静态内部类
静态内部类是一个定义在另一个类内部的类,但它不需要外部类的实例即可创建。静态内部类只能访问外部类的静态成员变量和静态方法。
7.HashCode在集合中的作用
hashCode()在集合中的作用主要是用来快速定位元素在哈希表(如HashMap和HashSet)中的位置。
Java的集合有两类,一类是List,还有一类是Set。前者有序可重复,后者无序不重复。
**在set中插入的时候怎么判断该元素已存在呢?**可以通过equals方法。但是如果元素太多,一个个equals,效率就会相当低下了。
当向集合添加元素时,集合会使用元素的hashCode()方法计算出一个哈希码,然后根据这个哈希码找到元素应该存放的位置。这样,当需要查找或操作某个元素时,集合可以直接定位到该位置,无需遍历整个集合,从而大大提高了效率。
8.Hash冲突怎么处理?
Hash冲突是指在哈希表中,两个不同的key经过哈希函数处理后得到了相同的哈希值,从而产生了冲突。处理Hash冲突的方法主要有以下几种:
- 链地址法:当发生冲突时,将具有相同哈希值的元素存储在一个链表中。
- 开放地址法:当发生冲突时,通过一定的探测方法在哈希表中寻找下一个可用的空槽位来存储元素。
- 线性探测:按顺序查找下一个空槽位。
- 二次探测:通过二次方的方式查找下一个空槽位。
- 双重哈希:使用另一个哈希函数来确定步长,从而查找下一个空槽位。
- 再哈希:当发生冲突时,使用不同的哈希函数再次计算键的哈希值,找到一个新的位置来存储元素。
- 建立公共溢出区:将哈希表分为基本表和溢出表两部分。当基本表发生冲突时,就把该元素存入溢出表。
9.深拷贝和浅拷贝的区别是什么?
深拷贝和浅拷贝在复制对象时的主要区别在于它们处理对象内部元素的方式。
深拷贝在复制对象时,会递归地复制原始对象及其所有子对象,包括对象的属性、嵌套对象、引用等。这意味着深拷贝会创建一个完全独立的新对象,修改原始对象不会影响复制对象。
浅拷贝在复制对象时,只复制最外层对象,对于内部的嵌套对象,仅仅是引用而已。意味着原始对象和浅拷贝对象之间共享内部对象,修改其中一个对象的内部对象会影响到另一个对象。
10. 你知道什么是fail-fast吗?
fail-fast是软件开发中的一种设计原则或模式。它指的是在程序执行过程中,一旦检测到异常或错误,就立即抛出异常并停止执行,以避免后续代码产生更严重的问题。这种策略被设计用来提高软件的可靠性和稳定性,防止问题持续扩散并造成更严重的后果。
在Java中,fail-fast是java.util包下的所有集合类的一种错误检测机制。当在多线程环境下,一个线程修改了集合,而另一个线程正在迭代该集合时,fail-fast行为会抛出ConcurrentModificationException异常。
下面是一个直观的fail-fast示例,它涉及两个线程:一个线程迭代集合,另一个线程修改集合。
11.介绍下你对红黑树的理解
请移步至《》
12.异常处理影响性能吗?
Java异常处理确实会对程序运行的速度产生一点影响。
想象一下,每次程序遇到异常,Java就会停下来,去创建一个记录异常的对象,并且还得记下当时程序正在做什么(调用栈信息)。这个过程需要花费一些时间,还可能占用一些额外的内存。
而且,当异常被抛出后,还需要暂停当前的程序执行,去找能处理这个异常的代码。这个查找过程涉及到对方法调用栈的遍历,是一个相对耗时的操作。
13.介绍下try-with-resource语法
try-with-resources 是 Java 7 引入的一个特性,它用于自动管理资源。这些资源通常需要在使用完毕后显式关闭,比如文件流、数据库连接等。
使用 try-with-resources 语句可以确保这些资源在 try 代码块执行完毕后被关闭,即使发生了异常也是如此。