文章已收录Github精选,欢迎Star:https://github.com/yehongzhi/learningSummary
前言
各位见面爱好者,我们又加瓦了!哈哈~
以下是我根据面试经验总结的一些常见的关于java基础的面试题目。做了一下总结,方便以后自己复习。
有需要的同学也可以收藏,后面我遇到新的面试题目会不断更新上去。
我尽量详细点回答,同学们千万不要死记硬背,要理解后用自己语言去总结概括,才能记得牢固。废话不多说,请看题吧~哈哈
创作不易,不要白票,点个赞吧,关注一下,大佬们。陆续更新。
微信公众号可搜索同名「 java技术爱好者 」
基础知识
JVM、JRE、JDK有什么联系与区别?
JVM是java虚拟机,能够将 class 文件中的字节码指令进行识别并调用操作系统向上的 API 完成动作。
JRE是java运行时环境,它主要包含两个部分,jvm 的标准实现和 Java 的一些基本类库。它相对于 jvm 来说,多出来的是一部分的 Java 类库。换句话说,JRE包含JVM。
JDK是java开发工具包,它集成了 jre 和一些好用的小工具。例如:javac.exe,java.exe,jar.exe 等。JDK包含JRE。
所以总得来说,JDK>JRE>JVM。
面向对象的特征有哪些?
有三大特征,继承,封装,多态。
为什么java可以实现跨平台?
因为java是编译成.class文件运行在JVM上的。针对不同的系统有不同的JVM实现,在不同的JVM实现上会映射到不同系统的 API 调用,从而实现代码的跨平台运行。
类的加载顺序?
静态成员变量、静态代码块、实例成员变量,实例代码块,构造器,实例方法。
接口和抽象类有什么共同点和不同点?
共同点:
1.都可以定义抽象方法,子类都要实现定义的抽象方法。
2.都不能被实例化,但是可以定义抽象类和接口类型的引用。
不同点:
1.接口没有构造器,抽象类可以定义构造器。
2.接口定义具体方法只能定义default修饰,抽象类可以直接定义具体方法。
3.接口的子类是实现接口,关键字是implements,抽象类的子类是继承,关键字是extends。
4.接口不能定义成员变量,只能定义常量。抽象类可以定义成员变量。
static关键字有哪些用法?
①修饰成员变量,用static修饰的成员变量就成为静态变量,静态变量只会存在一份,在类被加载时会初始化,且只会加载一次,通过类名访问。一般可以用static和final定义一些String类型,boolean类型,int类型的变量作为常量,可以减少资源的消耗。
②static修饰方法,该方法就被定义为静态方法,静态方法是不能被方法重写的,通过类名调用。一般用static定义一些工具类的方法。
③用static修饰代码块,该代码块就被定义为静态代码块,静态代码块在类初始化时被执行,且执行一次。一般用于初始化一些静态的成员变量的值。
Switch能用什么数据类型作为参数?
JDK1.5前:byte、short、char、int
JDK1.5:枚举
JDK1.7:String
枚举有哪些特点?在项目中如何使用?
特点:
1.枚举的构造器是私有的。
2.枚举不能被继承。
3.枚举是绝对的单例,即使是反序列化也无法创建多个实例。
使用场景:
当变量只能从一堆固定的值中取出一个时,那么就应该使用枚举。比如时间的单位,季度等等。
什么是方法重载?什么是方法重写?
方法重载,一个类中允许同时存在一个以上的同名方法,主要体现在方法参数的类型和数量不同,方法名相同,与访问修饰符和返回值类型都是无关的。口诀是"一同两不同"。
方法重写一般在继承中,子类重写父类的方法,既然是重写一遍,那么方法名和参数部分一定是相同的。只是实现的功能不同。声明为 final 的方法不能被重写,声明为 static 的方法不能被重写,声明为 private 的方法不能被重写。
静态变量和实例变量有什么不同?分别位于内存的什么区域?
1.静态变量使用static修饰,实例变量不需要。
2.静态变量在类被加载时就会分配内存空间,就可以使用。实例变量需要实例对象才会分配内存空间,才可以被引用,是属于实例的。
3.静态变量是存在于静态区(全局区)的,实例变量位于堆内存中。
java的内部类的分类有哪些?
实例内部类、静态内部类、局部内部类、匿名内部类。
break、continue、return 的作用是什么?
- break:结束循环。不仅可以结束其所在的循环,还可结束其外层循环。
- continue:跳过本次循环,开始下一次循环。
- return:不是专用于结束循环,而是用于结束方法。如果在循环中使用return,就会结束整个方法,循环当然也会结束。
Object类有哪些常用的方法?
toString()、equals()、hashCode()。
toString()
默认输出对象的内存地址,一般不希望输出内存地址可以重写toString()方法。equals()
方法用于比较对象是否相等,默认比较是内存地址,所以要正确比较两个对象是否值相等,此方法必须被重写。hashCode()
方法用来返回其所在对象的物理地址(哈希码值),常会和equals()
方法同时重写,确保相等的两个对象拥有相等的hashCode。
==与equals()的区别?
equals()
方法属于Object
对象的,所以比较基础数据类型是不能使用equals()
。必须使用==
。
在默认情况下,equals()
与==
是一样的,都是比较内存地址。所以在业务逻辑中,我们一般会重写equals()
方法。
equals()与hashCode()有什么联系?
1.equals()
相等的两个对象他们的hashCode()
肯定相等,也就是用equals()
对比是绝对可靠的。
2.hashCode()
相等的两个对象他们的equals()
不一定相等,也就是hashCode()
不是绝对可靠的。
在使用HashSet
或者HashMap
集合中,比较两个对象是否相等时,会先调用hashCode()
比较,如果hashCode()
相等,则会继续调用equals()
比较,equals()
也相等才会认为是同一个对象。如果hashCode()
返回不相等,则认为是不相等的对象。
所以一般我们会同时重写hashCode()
和equals()
方法。
& 和 &&有什么区别?
&&
具有短路的功能,也就是如果&&
左边的条件为fasle
就不再执行后面的条件判断。
&
则会执行完左右两边的条件判断。
final、finalize()、finally{}分别有什么作用?
final
修饰类,表明这个类不可被其他类继承。
final
修饰成员变量,表示此变量为常量,只能在初始化时被赋值一次,赋值后不能修改。
final
修饰方法。把方法锁定,不能被子类重写,以防止子类对其进行更改。
finalize()
是Object
里定义的,也就是说每一个对象都有这么个方法。这个方法在gc启动,该对象被回收的时候被调用。一个对象的finalize()
方法只会被调用一次。
finally
作为异常处理的一部分,它只能用在try/catch
语句中,并且附带一个语句块。
Cloneable接口有什么作用?
Cloneable
接口是一个标记接口,实现了此接口,表示可以使用clone()
方法,没有实现此接口使用clone()
会抛出CloneNotSupportedException
异常。
什么是浅克隆,什么是深克隆?
浅克隆是指拷贝对象时仅仅拷贝对象本身(包括对象中的基本变量),而不拷贝对象包含的引用指向的对象。
深克隆不仅拷贝对象本身,而且拷贝对象包含的引用指向的所有对象。
什么是序列化?什么是反序列化?
序列化:把对象转换为字节序列的过程称为对象的序列化。
反序列化:把字节序列恢复为对象的过程称为对象的反序列化。
Serializable接口有什么作用?
Serializable
接口是一个标记接口,一个类只有实现了Serializable
接口,它的对象才是可序列化的。否则序列化时会报NotSerializableException
异常。如果不显性声明serialVersionUID
,则会默认生成一个。为了serialVersionUID
的确定性,最好是显性声明。
String、StringBuffer、StringBuilder有什么区别?
String
被声明为final class
,是由定义final
的字符数组实现的,因为它的不可变性,所以拼接字符串时候会产生很多无用的中间对象,如果频繁的进行这样的操作对性能有所影响。StringBuffer
是由定义了临时数据transient
的字符数组实现的,提供append()
和add()
方法,可以将字符串添加到已有序列的末尾或指定位置,它的本质是一个线程安全的可修改的字符序列,所有修改数据的方法都加上synchronized
。性能相对StringBuilder
会差一点。StringBuilder
和StringBuffer
本质上没什么区别,区别是去掉了保证线程安全的synchronized
,减少了开销,性能有所提高。
什么是泛型?什么是泛型的上界和下界?
Java 泛型是 JDK1.5中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。
上界用extends
关键字声明,表示参数化的类型可能是所指定的类型,或者是此类型的子类。
下界用super
进行声明,表示参数化的类型可能是所指定的类型,或者是此类型的父类型,直至Object。
什么是反射机制?
Java反射机制是在运行状态中,对于任意一个类,都能够获得这个类的所有属性和方法,对于任意一个对象都能够调用它的任意一个属性和方法。这种在运行时动态的获取信息以及动态调用对象的方法的功能称为Java的反射机制。
获取Class对象的方式有哪些?
- 通过
Object
类中的getClass()
方法,想要用这种方法必须要明确具体的类并且创建该类的对象。 - 所有数据类型都具备一个静态的属性
.class
来获取对应的Class
对象。但是还是要明确到类,然后才能调用类中的静态成员。 - 通过
Class.forName()
方法完成,必须要指定类的全限定名,由于前两种方法都是在知道该类的情况下获取该类的字节码对象,因此不会有异常,但是Class.forName()
方法如果写错类的路径会报ClassNotFoundException
的异常。
java中的异常有哪几种异常?
Throwable
类是Java
异常类型的顶层父类,Throwable
包含了Error
和Excetion
。Excetion
分为两种,一种是非运行时异常(又称为检查异常),另一种是运行时异常(RuntimeException)。
java是如何处理异常的?
Error
是程序无法处理的, 比如OutOfMemoryError
、OutOfMemoryError
等等, 这些异常发生时,JVM
一般会终止线程。- 运行时异常(
RuntimeException
),如NullPointerException
、IndexOutOfBoundsException
等,是在程序运行的时候可能会发生的,所以程序可以捕捉,也可以不捕捉。这些错误一般是由程序的逻辑错误引起的,程序应该从逻辑角度去尽量避免。 - 非运行时异常是
RuntimeException
以外的异常,是Exception
及其子类,这些异常从程序的角度来说是必须经过捕捉检查处理的,否则不能通过编译。如IOException
、SQLException
等。
java集合、IO流、日期处理等
常用的集合有哪些?
常用集合有Map、List、Set。
HashMap是线程安全的吗?
不是线程安全的。
如何使HashMap线程安全?
使用Collections
类的synchronizedMap()
方法包装。
Map<String, Object> map = Collections.synchronizedMap(new HashMap<>());
使用java.util.concurrent
包下的ConcurrentHashMap
类也可以获得线程安全的Map。
ConcurrentHashMap concurrentHashMap = new ConcurrentHashMap();
使用Hashtable
类,也可以获得线程安全的Map
Map<String,Object> hashtable = new Hashtable<>();