1.什么是面向对象,谈谈你对面向对象的理解?
-
面向对象是一种思想,简单来说就是将数据和操作数据的方法封装在对象中。举个例子来说比如洗衣机洗衣服。我们通常会把这个拆分成两个对象——人和洗衣机。人需要干的就是:打开洗衣机—放入衣服—放入洗衣液—关闭洗衣机门-按下各种开关,洗衣机则负责:清洗—烘干
-
面向对象拥有三大特性其实也可以说四大特性:封装–继承–多态–抽象
- 相等于封装来说,就是把一切内部信息隐藏起来,对外不透明,只提供最简单的调用。
- 继承是从已有的一个类得到信息并创建新类的过程,一般我们称这个提供信息的类为父类,得到信息的的类为子类。子类可以扩展自己的信息,按我自己的理解,继承就是一种信息复用,也是信息延申的一个手段。
- 多态存在的必要三个条件就是继承,方法的重写,父类引用指向子类对象。就是多个子类继承一个父类,但是重新修改了分享信息的内容,然后通过同样的对象引用调用同样的方法,但是得出不同的信息。多态性其实还分为编译时多态性和运行时多态性,方法重载实现的是编译时多态性(也称为前绑定),方法重写实现的是运行时多态性(也成为后绑定)。
- 抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面,抽象只关注对象的哪些属性和行为,并不关注这此行为的细节是什么
PS:我还在思考抽象算不算特性!!!!有人说仁者见仁,智者见智。可以是三种也可以是四种
2.== 和equals的区别 ======+2
- 首先,==是等于比较运算符,而equals是object里面的一个方法
- ==对于基本数据类型来说,比较的是值,对于引用数据类型来书,比较的是内存地址
- equals默认情况下也是比较内存地址,但是我们一般会重写equals使其变为内容比较,即值比较
3.final 在 java 中有什么作用————被问+1
- final修饰的类叫最终类,该类不能被继承
- final修饰的方法不能被重写
- final修饰的变量叫常量,常量必须初始化,初始化之后的值不能被修改。
篇幅限制下面就只能给大家展示小册部分内容了,这边整理了一份核心面试笔记包括了:Java面试、Spring、JVM、MyBatis、Redis、MySQL、并发编程、微服务、Linux、Springboot、SpringCloud、MQ、Kafka 面试专题
需要全套面试笔记的【点击此处即可】免费获取
package java_interviewtopic_01.stage01;
import java.util.ArrayList;
import java.util.List;
/**
* 3.final
*/
public class Interview03 {
// 使用final修饰的静态类变量需要再声明的时候就赋值或者在静态代码块赋值
final static String i = "I"; // 声明时赋值
// static {
// i = "I"; // 在静态代码块中赋值
// }
// 使用final修饰的类变量需要再声明的时候就赋值或者在代码块赋值和构造函数的赋值
final String j = "J";
// {
// j = "J"; // 在代码块中赋值
// }
// public Interview03(String j) {
// this.j = j; // 在构造函数中赋值
// }
public static void main(String[] args) {
// 局部变量可以先声明后赋值,但是赋值之后也不能再更改了
final String a;
a = "abc";
final List<Integer> list = new ArrayList<>();
list.add(2);
list.add(3);
list.add(4);
list.add(5); // 可以看出内容可以变
// list会爆红
list = new ArrayList<>(); // 可以看出地址不能变了
}
}
PS:当final修饰的变量是一个基本数据类型的时候,这个变量初始化之后的值不能再被更改。但是当final修饰的是一个引用数据类型的时候,该引用的内存地址不能再更改,但是该地址的内容可以改变
4.java 中操作字符串都有哪些类?它们之间有什么区别?===========被问+1
- String StringBuffer StringBuilder
- 三者共同之处:都是final类,不能被继承
- StringBuffer与StringBuilder两者共同之处:可以通过append、indert进行字符串的操作。
- 再说这三个类的主要区别:其主要区别在两个方面,即运行速度和线程安全两个方面
-
先说运行速度,在这方面运行速度快慢为:StringBuilder > StringBuffer > String。String慢的原因:因为Stirng为字符常量,而另外两个均为字符串变量。
-
String的课外补充:写个例子:Stirng a = “123” 再将a = a + “45” 这时打印出a = “12345”这个例子看似这个a被更改了。其实不是,这只是一个假象而已。JVM对于这几行代码是这样处理的,首先创建一个String对象a。并把123赋值给a其实在a = a + “45”的时候,JVM又创建了一个新的对象也名为a。然后再把原来的a的值和”45”加起来再赋值给新的a。而原来的a就会被回收机制给回收掉。所以,a实际上并没有被更改,也就是前面说的String对象一旦创建之后不可更改了。
-
Java中对String对象进行的操作实际上是一个不断创建新的对象并且将旧的对象回收的一个过程,所以执行速度很慢。而StringBuilder和StringBuffer的对象是变量,对变量进行操作就是直接对该对象进行更改,而不进行创建和回收的操作,所以速度要比String快很多。
-
再说这个线程安全:StringBuilder是线程不安全的,而StringBuffer是线程安全的
-
如果一个StringBuffer对象在字符串缓冲区被多个线程使用时,StringBuffer中很多方法可以带有synchronized关键字,所以可以保证线程是安全的,但StringBuilder的方法则没有该关键字,所以不能保证线程安全,有可能会出现一些错误的操作。所以如果要进行的操作是多线程的,那么就要使用StringBuffer,但是在单线程的情况下,还是建议使用速度比较快的StringBuilder。
篇幅限制下面就只能给大家展示小册部分内容了,这边整理了一份核心面试笔记包括了:Java面试、Spring、JVM、MyBatis、Redis、MySQL、并发编程、微服务、Linux、Springboot、SpringCloud、MQ、Kafka 面试专题
需要全套面试笔记的【点击此处即可】免费获取
PS:总结一下:
- String:适用于少量的字符串操作的情况
- StringBuilder:适用于单线程下在字符缓冲区进行大量操作的情况
- StringBuffer:适用多线程下在字符缓冲区进行大量操作的情况
5.重载(Overload)和重写(Override)的区别。重载的方法能否根据返回类型进行区分?
-
区别:方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性具体回答:重载发生在同一个类中,方法名一样,但是参数类型不一样,个数不一样,方法返回值和访问修饰符可以不同。重写发生在父子类中,方法名,参数必须相同,返回值范围小于等于父类,抛出的异常范围小于等于父类,访问修饰符范围大于等于父类。
-
不能根据返回值类型来区分:这个时候如果出现这种情况:
- float max ( int a , int b );
- int max ( int a , int b );
- 编译器就不知道该调用哪个了。
6.接口和抽象类有什么区别?=======+1
-
定义:接口定义了一组方法的契约,而不包含具体的实现代码。它只声明了方法的名称、参数和返回类型,但没有提供方法的实现细节。抽象类是一个可以包含抽象方法的类,它可以定义方法的实现和属性。
-
多继承:接口支持多重继承,一个类可以实现多个接口,以便获得不同的行为和能力。抽象类不支持多重继承,一个类只能继承一个抽象类。
-
实现:类通过实现接口来表明它们具有特定的行为或能力。一个类可以实现多个接口,并且必须实现接口中声明的所有方法。抽象类可以被继承,并可以提供一些默认的方法实现,子类可以选择性地覆盖或继承这些方法。
-
构造函数:接口不能包含构造函数,因为接口只是一组方法的契约。抽象类可以包含构造函数,它可以被子类继承和调用。
-
访问修饰符:接口中的方法默认是公共的,不能有访问修饰符。抽象类中的方法可以有不同的访问修饰符,如公共(public)、私有(private)、受保护(protected)等。
-
代码复用:通过实现接口,一个类可以重用多个接口中定义的方法。抽象类可以通过被继承来实现代码的复用。
PS:总的来说,接口主要用于定义契约和行为规范,而抽象类主要用于提供一些默认的方法实现和属性,
以及为子类提供代码复用的机制。选择使用接口还是抽象类取决于具体的设计需求和代码结构。
7.List、Set之间的区别是什么?
-
重复元素:List允许包含重复的元素,而Set不允许重复元素。当向List中添加元素时,无论元素是否已经存在,
都会被添加到List中。而向Set中添加元素时,如果元素已经存在于Set中,则添加操作将被忽略。 -
顺序性:List是有序的集合,它维护元素的插入顺序。元素在List中的位置是由插入顺序决定的,
可以通过索引访问和操作元素。Set是无序的集合,它不保留元素的插入顺序。元素在Set中的存储位置由Set的实现决定,
无法通过索引访问元素。 -
数据结构:List通常使用动态数组(如ArrayList)或链表(如LinkedList)实现,
这些数据结构提供了快速的随机访问或插入/删除操作。Set通常使用哈希表(如HashSet)或平衡二叉树(如TreeSet)实现,
这些数据结构提供了高效的元素查找和去重操作。 -
主要操作:List提供了通过索引访问元素、在指定位置插入/删除元素、获取列表大小等操作。
Set提供了添加元素、删除元素、判断元素是否存在等主要操作。 -
迭代顺序:List可以通过迭代器按顺序访问集合中的元素。Set的迭代顺序是不确定的,取决于底层数据结构的实现方式。
PS:需要根据具体的需求选择使用List还是Set。如果需要保留元素的插入顺序并且允许重复元素,应该选择List。如果需要高效地进行元素去重和判断元素是否存在的操作,可以选择Set。
8.两个对象的 hashCode()相同,则 equals()也一定为 true,对吗?
-
不对
-
因为hashcode方法一般用作于哈希表数据结构,在集合中要存入一个元素的时候,首先调用hashcode方法得出hash值,然后将hash值转换为数组下标,然后拿着该下标去对应的位置,如果该位置没有任何的元素,那么就直接将值存入。如果已经存在改值,那么则进行equals比较,如果返回为false,那么将其存入进去,如果返回为true,则覆盖元素。
-
结论:hashCode()相等的两个对象他们的equal()不一定相等,也就是hashCode()不是绝对可靠的。equals相等的两个对象它们的hashcode一定相等,也就是equals对比是绝对可靠的。
PS:hashCode()相等即两个键值对的哈希值相等,然而哈希值相等。并不一定能得出键值对相等
9.java 中的 Math.round(-5.5) 等于多少?
等于-5,在java中,四舍五入的原理是在原参数上加0.5再做向下取整。
10.String str=”i”与 String str=new String(“i”)一样吗?
- 不一样,两个内存分配的方式不一样
- String str = “i” 的方式java会把它分配到常量池
- String str = new String(“i”) 会分配到堆内存中
11. String s = new String(“xyz”);创建了几个String对象?
这个要看情况,当常量池中没有”xyz”的时候,他会先在常量池中创建这个字符串对象,然后再创建这个字符串的引用对象,所以这时候是两个对象。当常量池中有这个”xyz”的时候,就只会创建这个字符串的引用对象,即一个对象
12. ArrayList 和 LinkedList 的区别是什么?————被问+1
- 内部实现:
- ArrayList内部使用一个动态数组来存储元素。它可以根据需要自动调整数组的大小,支持随机访问和快速的索引操作。
插入和删除元素时,可能需要移动后续元素来填补空缺或调整数组大小。 - LinkedList内部使用一个双向链表来存储元素。每个节点都包含元素本身和指向前一个和后一个节点的引用。
它支持快速的插入和删除操作,但访问特定索引的元素需要从头部或尾部开始遍历链表。
- 访问操作:
-. ArrayList支持快速的随机访问,可以通过索引直接访问和修改元素。时间复杂度为O(1)。
-. LinkedList的访问操作需要从头部或尾部开始遍历链表,直到达到目标索引。访问特定索引的元素需要遍历链表,
时间复杂度为O(n)。
篇幅限制下面就只能给大家展示小册部分内容了,这边整理了一份核心面试笔记包括了:Java面试、Spring、JVM、MyBatis、Redis、MySQL、并发编程、微服务、Linux、Springboot、SpringCloud、MQ、Kafka 面试专题
需要全套面试笔记的【点击此处即可】免费获取
- 插入和删除操作:
- ArrayList在末尾进行插入和删除操作效率较高,时间复杂度为O(1)。但在中间位置进行插入和删除操作需要移动后续元素,
时间复杂度为O(n)。 - LinkedList在任意位置进行插入和删除操作效率较高,只需要调整相邻节点的引用,时间复杂度为O(1)。
但在特定位置的访问操作效率较低,时间复杂度为O(n)。
- 内存占用:
- ArrayList在内存中连续存储元素,因此它的内存占用相对较小。
- LinkedList的每个节点都需要额外的空间来存储前后节点的引用,因此它的内存占用相对较大。
PS:综上所述,ArrayList适合需要频繁访问和修改元素的场景,而LinkedList适合需要频繁插入和删除元素的场景。选择哪个实现类取决于具体的需求和操作模式。
13. HashMap 的实现原理?
-
哈希函数:HashMap 使用哈希函数将键映射到哈希表的索引位置。哈希函数通常根据键的哈希码计算,哈希码是一个整数值,
用于表示键的特征。Java 中的对象通过 hashCode() 方法获取哈希码。 -
数组和链表/红黑树:HashMap 内部使用数组存储元素。数组的每个位置称为桶(bucket),
每个桶可以存储一个链表或红黑树的根节点。当多个键映射到同一个桶时,它们将以链表或红黑树的形式存储在该桶中。 -
冲突处理:由于哈希函数的映射范围可能小于键的数量,不同的键可能会映射到相同的桶中,这称为哈希冲突。
当发生冲突时,HashMap 使用链表或红黑树来解决。初始情况下,所有键都存储在链表中。 -
插入操作:当执行插入操作时,首先根据键的哈希码计算桶的索引位置。如果桶为空,则直接将键值对存储在该桶中。
如果桶非空,表示存在冲突,则遍历桶中的链表或红黑树,根据键的哈希码和 equals() 方法判断键是否已经存在。
如果键已存在,则更新对应的值;如果键不存在,则将新的键值对插入到链表或红黑树的末尾。 -
查找操作:执行查找操作时,根据键的哈希码计算桶的索引位置。如果桶为空,则键不存在;如果桶非空,
则遍历链表或红黑树,根据键的哈希码和 equals() 方法判断键是否匹配。如果找到匹配的键,则返回对应的值;
如果遍历结束仍未找到匹配的键,则键不存在。 -
删除操作:执行删除操作时,根据键的哈希码计算桶的索引位置。如果桶为空,则键不存在;如果桶非空,
则遍历链表或红黑树,根据键的哈希码和 equals() 方法判断键是否匹配。如果找到匹配的键,
则将对应的节点从链表或红黑树中删除
PS:hashMap的put原理: hashMap的底层采用数组和链表以及红黑树(jdk1.8)的数据结构。当我们往HashMap里面put元素的时候,底层调用k的hashcode方法得到hash值,然后通过哈希算法将hash值转换为数组的下标,当下标上没有任何元素的时候,就把这个节点放在这个位置上,如果下标对应的位置上有链表,此时会拿着k和链表上的k进行equals比较,如果和所有链表上的k进行equals比较都是返回false,则将其存入末尾(1.7是头部),如果有一个返回为true,则将它的值覆盖,如果添加时发现容量不够,就开始扩容。
补充点:在jdk8版本的时候haspMap在第一次添加数据时,默认构造函数构建的初始容量是16,当达到它的临界值(0.75)的时候,数组就会扩容,如果有一条链表的元素个数到达8,且数组的大小到达64时。就会进化成红黑树,当数组的长度重新低于6的时候,又会将红黑树重新转换为链表。
PS:hashMap的get(k)原理:先调用k的hashcode方法得出hash值,通过哈希算法将hash值转换为数组下标,通过数组下标快速定位,如果该位置上什么都没有,则返回null。如果该位置有链表,那么拿着该k和链表上的所有k进行equals比较, 如果所有equals都返回false则返回null,但是只要其中一个节点返回true,则将其value返回。
14. 说一下 HashSet 的实现原理?
- HashSet底层由HashMap实现,扩容机制一样。它封装了一个HashMap来存储所有的集合元素。但是它不一样的是,它的所有集合元素由HashMap的key来保存,而HashMap的value则存储了一个PRESENT。它是一个静态的 Object 对象。
- HashSet的其它操作原理都是基于HashMap的
15. HashMap 和 Hashtable 有什么区别?
-
线程安全性:Hashtable是线程安全的,它的方法都是同步的,可以在多线程环境下使用。而HashMap则是非线程安全的,
它的方法没有进行同步处理,如果在多线程环境下使用,需要手动进行同步操作。 -
null值:Hashtable不允许键或值为null,如果尝试存储null键或值,将会抛出NullPointerException。
而HashMap允许键和值都为null,可以存储null键和null值。 -
继承关系:Hashtable是早期Java版本中提供的类,它是Dictionary类的子类。
而HashMap是Java Collections Framework中的一部分,它是AbstractMap类的子类。 -
迭代器:Hashtable的迭代器是通过Enumeration实现的,而HashMap的迭代器是通过Iterator实现的。
Iterator提供了更强大的迭代功能,可以同时进行遍历和删除操作。 -
初始容量和扩容机制:Hashtable初始化容量是11,扩容是2n+1,hashmap初始化容量是16,扩容是2n
-
性能:由于Hashtable是线程安全的,它的方法都进行了同步处理,这可能会导致在性能方面的一些开销。相比之下,HashMap不进行同步操作,因此在单线程环境下通常具有更好的性能。
PS: 综上所述,如果在多线程环境下需要线程安全的操作,可以选择Hashtable。而在单线程环境下,或者需要更高的性能和灵活性,可以选择HashMap。
16. HashSet与HashMap的区别?
-
存储结构:HshMap存储键值对,HashSet存储对象
-
存储内容:HashSet不允许重复的元素。HashMap每个键都是唯一的,但值可以重复。
-
使用方式:HashMap使用put添加元素值,HshSet使用add方法
-
实现接口:HashMap实现了Map接口,HashSet实现了set接口
-
存储效率:HashSet 的存储效率比较高,因为它只需要存储单个元素。HashMap 的存储效率相对较低,
因为它需要存储键值对,并且需要处理键的哈希冲突。 -
计算hashCode的方式不同:HashMap使用键(key)来计算hashCode, HashSet使用成员对象来计算hashcode的值,对于两个对象来说,他们的hashcode值可能相同,所以用equals()方法来判断对象的相等性。如果两个对象不相等的话返回false
PS:需要注意的是,HashSet 实际上是通过 HashMap 来实现的,它使用 HashMap 的键作为元素的存储和查找依据,值则统一为一个常量对象。因此,HashSet 的实现可以看作是对 HashMap 的简化和特化。
17. &和&&的区别?======+1
- &和&&都表示与的意思,既表达式俩边都成立,结果才成立
- &做逻辑运算符时,左边为假时,它还会计算右边,而&&(短路与)不会,当左边为假时后面则不会计算了
- &做位运算符时,&的左右俩边可以是布尔类型,也可以是数值,而&&只能是布尔类型
18. 字符串连接用+和StringBuilder的append的区别?
- 一般情况下没什么区别,因为一般情况下用+连接,系统内部会进行优化,它用的也是StringBuilder的append来实现的
- 但是在循环拼接的时候,用的如果是+拼接的话,就是一直在循环内部创建StringBuilder对象,这样会造成空间浪费。但是我们直接用StringBuilder的话,可以定义在循环外面。减少内存消耗
// 建议使用
StringBuilder stringBuilder = new StringBuilder("123");
for (int j = 0; j < 10; j++) {
// 这里使用的是外部创建的StringBuilder,就只用一个
stringBuilder.append(j);
}
// 不建议使用
String a = "tt";
for (int j = 0; j < 10; j++) {
// 这里会一直创建StringBuilder,然后进行append。
a += j;
}
-
篇幅限制下面就只能给大家展示小册部分内容了,这边整理了一份核心面试笔记包括了:Java面试、Spring、JVM、MyBatis、Redis、MySQL、并发编程、微服务、Linux、Springboot、SpringCloud、MQ、Kafka 面试专题
需要全套面试笔记的【点击此处即可】免费获取
19. String有哪些特性?
- 不可变,为什么不可变可以查看第四题的课外补充
- 常量池优化:String 对象创建之后,会在字符串常量池中进行缓存,如果下次创建同样的对象时,会直接返回缓存的引用
- 使用 final 来定义 String 类,表示 String 类不能被继承,提高了系统的安全性
20. Integer a= 127 与 Integer b = 127相等吗?那Integer a1 = 128 与 Integer b1 = 128 呢?
- 前者相等,后者不相等
- 因为如果整型字面量的值在-128到127之间,那么自动装箱时不会new新的Integer对象,而是直接引用常量池中的Integer对象,超过这个范围 则会new 新的Integer对象,即a1==b1的结果是比较内存地址,所以不相等
21.this关键字的用法?
-
引用当前对象:this 可以用于引用当前对象,在类的方法中可以通过 this 来访问当前对象的成员变量和方法。
例如,this.name 表示当前对象的 name 成员变量,this.method() 表示调用当前对象的 method() 方法。 -
区分同名的成员变量和方法:当成员变量和方法名称相同,且需要在方法内部访问成员变量时,
可以使用 this 关键字来明确指定是访问成员变量还是方法。例如,this.name 表示当前对象的成员变量 name,
而 name() 表示调用当前对象的 name() 方法。 -
在构造方法中调用其他构造方法:在一个类中可以定义多个构造方法,而且一个构造方法可以调用同一个类中的其他构造方法。
使用 this 关键字可以在构造方法中调用其他构造方法。例如,this(parameters) 可以调用具有相应参数的其他构造方法。 -
返回当前对象:在方法中,如果需要返回当前对象本身,可以使用 return this 语句。这在实现方法链式调用时很常见。
PS: 总结起来,this 关键字在Java中用于引用当前对象,区分同名的成员变量和方法,调用其他构造方法以及返回当前对象本身。
22.static存在的主要意义?
-
共享数据:静态成员属于类,而不是类的实例。静态成员在类加载时被初始化,并且在整个程序执行期间只有一份拷贝。因此,静态成员可以被多个对象共享,可以在不创建对象的情况下访问和修改。
-
节省内存:由于静态成员只有一份拷贝,不需要每个对象都创建一份,可以节省内存空间。对于大量对象共享相同数据的情况,使用静态成员可以降低内存开销。
-
方便访问:静态成员可以通过类名直接访问,而不需要通过对象引用。这样可以简化访问代码,提高代码的可读性和易用性。
-
静态代码块:static关键字还有一个比较关键的作用就是 用来形成静态代码块以优化程序性能,static块可以置于类中的任何地方,类中可以有多个static块。在类初次被加载的时候会按照static块的顺序来执行每个static块,并且只会执行一次
PS:需要注意的是,静态成员有一些限制和注意事项:
- 静态成员只能访问其他静态成员,不能直接访问非静态成员。
- 静态成员不能引用
this
关键字,因为它们不依赖于实例。 - 静态成员的生命周期与类的生命周期相同,它们在类被加载时初始化,直到程序结束或类被卸载才被销毁。
PS:总结起来,static关键字的主要意义是共享数据、节省内存、方便访问,以及定义静态块和静态方法。
23.为什么说static块可以用来优化程序性能?
-
静态块的执行时机:静态块在类加载时执行,而不是在对象实例化时执行。这意味着静态块的初始化操作只会执行一次,并且在程序的整个生命周期内保持有效。这可以避免重复的初始化操作,提高程序的性能。
-
提前初始化:静态块可以在类加载时进行一些提前的初始化操作,例如读取配置文件、建立连接等。
通过在静态块中执行这些操作,可以避免在实际使用时再进行初始化,从而减少了延迟和初始化过程的开销,提高了程序的响应速度。 -
资源预加载:静态块可以用来预加载一些资源,例如将数据加载到缓存中,提前准备好一些常用的计算结果等。这样可以避免每次需要资源时都进行加载和计算,从而减少了运行时的开销,提高了程序的执行效率。
PS:总结起来,通过在静态块中进行提前初始化、资源预加载等操作,可以避免重复的初始化和延迟操作,从而提高程序的性能和响应速度。静态块在适当的情况下可以作为一种性能优化的手段之一。
PS(简答):因为它的特性:只会在类加载的时候执行一次。因此,很多时候会将一些只需要进行一次的初始化操作都放在static代码块中进行
24.创建一个对象用什么关键字?对象实例与对象引用有何不同?
1.创建对象使用关键字 “new”
-
对象实例是指类的具体实体,它占用内存并在运行时存在。当你使用 “new” 关键字创建一个对象时,系统将分配内存来存储该
对象的实例。(对象实例在堆内存中) -
对象引用是指访问对象的变量或标识符。它们实际上只是存储对象内存地址的变量。当你创建一个对象时,实际上创建的是对象
的实例,而引用变量只是指向该实例的一个引用。你可以使用引用变量来操作和访问对象的属性和方法。(对象引用存放在栈内存中)
PS:简而言之,对象实例是指对象在内存中的实体,而对象引用是指用于访问对象的变量。你可以通过对象引用来操作对象,
包括调用对象的方法和访问其属性
25.在Java中定义一个不做事且没有参数的构造方法的作用?—-即空构造方法
Java程序在执行子类的构造方法之前,如果没有用super()来调用父类特定的构造方法,则会调用父类中“没有参数的构造方法”。因此,如果父类中只定义了有参数的构造方法,而在子类的构造方法中又没有用super()来调用父类中特定的构造方法,则编译时将发生错误,因为Java程序在父类中找不到没有参数的构造方法可供执行。解决办法是在父类里加上一个不做事且没有参数的构造方法
26.一个类的构造方法的作用是什么?若一个类没有声明构造方法,该程序能正确执行吗?为什么?
- 主要作用是完成对类对象的初始化工作
- 可以执行
- 因为一个类即使没有声明构造方法也会有默认的不带参数的构造方法
27.静态变量和实例变量区别?======+1
- 存储位置和创建节点:
- 实例变量:每个类的实例都有自己的实例变量副本,它们存储在对象的堆内存中。每当创建一个类的新实例时,
就会分配实例变量的新副本。 - 静态变量:静态变量在类的加载过程中被分配内存,并且在整个程序运行期间只有一个副本。它们存储在静态存储区域,
通常是在静态数据区域。
- 生命周期:
- 实例变量:实例变量的生命周期与对象的生命周期相同。当对象被创建时,实例变量被初始化,而当对象被销毁时,
实例变量也会随之销毁。 - 静态变量:静态变量在程序开始运行时初始化,并在整个程序执行期间保持不变,直到程序终止。它们不依赖于任何特定的实例。
- 访问方式:
- 实例变量:实例变量只能通过对类的实例进行引用来访问。每个实例都有自己的实例变量副本,
因此可以在每个实例上进行不同的赋值和访问。 - 静态变量:静态变量可以通过类名直接访问,不需要创建类的实例。所有实例共享同一个静态变量副本。
- 使用场景:
- 实例变量:实例变量适用于每个对象具有不同状态或属性的情况。它们在类的实例之间具有独立性,并且可以根据对象的特定
需求进行不同的赋值。 - 静态变量:静态变量适用于在多个对象之间共享状态或属性的情况。它们在类的所有实例之间是共享的,可以在不创建
类的实例的情况下访问和修改。
PS:实例变量是每个对象独立拥有的,每个对象都有自己的一份副本,而静态变量在类加载时初始化,整个程序运行期间只有一份副本,
可以被所有对象共享。
28.静态方法和实例方法有何不同?
- 内存分配:
- 实例方法:每个类的实例都有自己的一份实例方法的副本,分配在堆内存中
- 静态方法:在类的加载过程中被分配内存,并在整个程序运行期间只有一份副本,分配在静态存储区域。
- 访问方式:
- 实例方法:实例方法必须通过类的实例来调用。在实例方法内部,可以使用关键字 “this” 引用当前对象。
- 静态方法:静态方法可以直接通过类名来调用,而不需要创建类的实例。它们不能使用关键字 “this”,因为静态方法不依赖于特定的对象实例。
- 访问权限
篇幅限制下面就只能给大家展示小册部分内容了,这边整理了一份核心面试笔记包括了:Java面试、Spring、JVM、MyBatis、Redis、MySQL、并发编程、微服务、Linux、Springboot、SpringCloud、MQ、Kafka 面试专题
需要全套面试笔记的【点击此处即可】免费获取
- 静态方法在访问本类的成员时,只允许访问静态成员(即静态成员变量和静态方法),而不允许直接访问实例成员变量和实例方法;实例方法则无此限制
- 继承和重写:
- 实例方法:实例方法可以被子类继承和重写。当子类定义与父类相同的实例方法时,可以使用方法重写来改变方法的行为。
- 静态方法:静态方法不能被子类重写。子类可以定义与父类相同的静态方法,但是这只是方法的隐藏,而不是重写。
29.对象的相等与指向他们的引用相等,两者有什么不同?
对象的相等 比的是内存中存放的内容是否相等而 引用相等 比较的是他们指向的内存地址是否相等
30.java 中 IO 流分为几种?
-
按功能来分:输入流(input)、输出流(output)
-
按类型来分:字节流和字符流
- 字节流和字符流的区别是:字节流按 8 位传输以字节为单位输入输出数据,字节流用于处理二进制数据
字节流: InputStream,OutputStream - 字符流按 16 位传输以字符为单位输入输出数据,字符流用于处理文本数据
字符流: Reader,Writer
31.Java中的I/O流分为哪些层次
- 字节流抽象类层次:
- InputStream:字节输入流的抽象类,用于从数据源读取字节数据。
- OutputStream:字节输出流的抽象类,用于向目标写入字节数据。
- 字符流抽象类层次:
- Reader:字符输入流的抽象类,用于从数据源读取字符数据。
- Writer:字符输出流的抽象类,用于向目标写入字符数据。
- 字节流与字符流桥接层次:
- InputStreamReader:将字节流转换为字符流的桥接类。
- OutputStreamWriter:将字符流转换为字节流的桥接类。
- 高级I/O流层次:
在字节流和字符流的基础上,Java还提供了一些高级I/O流,用于更方便地进行数据处理,如:
- BufferedInputStream 和 BufferedOutputStream:提供缓冲功能,加快读写速度。
- BufferedReader 和 BufferedWriter:提供缓冲功能和一次读取一行的能力。
- DataInputStream 和 DataOutputStream:用于读写Java基本数据类型和字符串。
- ObjectInputStream 和 ObjectOutputStream:用于读写Java对象。
这些层次的结构使得Java中的I/O操作更加灵活,可以根据不同的需求选择合适的类进行数据的读取和写入。
32.什么是处理流(Filter Streams)?什么是节点流(Node Streams)?
-
处理流:处理流是对节点流的包装,提供了额外的功能。它们可以提供缓冲、数据转换、对象序列化等功能,以简化I/O操作。
-
节点流:节点流是直接与数据源或目标连接的I/O流。它们用于读取或写入数据,例如文件流(FileInputStream、FileOutputStream)和网络流(SocketInputStream、SocketOutputStream)
33.Java中常用的I/O流类有哪些?
Java中常用的I/O流类包括FileInputStream、FileOutputStream、BufferedInputStream、BufferedOutputStream、FileReader、FileWriter、BufferedReader、BufferedWriter等
34.如何使用Java中的序列化(Serialization)?
序列化是将对象转换为字节流的过程,以便在网络传输或持久化存储中使用。要实现序列化,需要让类实现Serializable接口,并使用ObjectInputStream和ObjectOutputStream进行读写操作。
篇幅限制下面就只能给大家展示小册部分内容了,这边整理了一份核心面试笔记包括了:Java面试、Spring、JVM、MyBatis、Redis、MySQL、并发编程、微服务、Linux、Springboot、SpringCloud、MQ、Kafka 面试专题
需要全套面试笔记的【点击此处即可】免费获取