Java面试题整理《基础篇》,2024年最新分布式架构面试

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip1024b (备注Java)
img

正文


封装:

封装指隐藏对象的状态信息(属性),不允许外部对象直接访问对象的内部信息。但是可以提供一些可以被外界访问的方法来操作属性。通过封装,明确标识出允许外部使用的所有成员函数项,而其内部细节则对外部调用透明,外部调用者无需去关心其具体内部实现。

继承:

  • 当多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承单独的那个类即可。多个类可以称为子类,单独这个类称为父类或者超类。

  • 继承是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的属性或方法(对父类进行扩展),也可以拥有父类的属性和方法,并且通过自己的方法再次实现父类的方法(重写)。通过使用继承,可以快速地创建新的类,可以提高代码的重用,程序的可维护性,节省大量创建新类的时间 ,提高我们的开发效率。

  • Java只支持单继承,不支持多继承。一个类只能有一个父类,不可以有多个父类。Java支持多层继承(继承体系)。Java继承了父类非私有的成员变量和成员方法,但是请注意:子类是无法继承父类的构造方法的。

多态:

  • 多态:一种事物的多种形态(多态的前提:继承、重写、向上转型),比如说所属类不同的对象,在调用其共同父类的方法时,会产生不同的执行结果。

  • 通过多态可以提高代码的可重用性,降低模块之间的耦合度。(在Java中方法的重载和重写是实现多态的2种方式。)

重载和重写的区别?


  • 重载:同一个类中定义了多个方法名相同而参数不同的方法,这些⽅法能够根据输⼊数据的不同,做出不同的处理。

  • 重写:子类从父类继承的某个实例方法无法满足子类的功能需要时,需要在子类中对该实例方法进行重新实现,这样的过程称为重写,也叫做覆写、覆盖。

重载在同一个类中,方法名相同,参数不同(参数的个数、顺序、类型不同),⽅法返回值和访问修饰符可以不同。

方法重写的前提:继承,要求方法名、参数列表、返回值类型必须相同,子类的修饰符大于等于父类,抛出的异常范围⼩于等于⽗类。

重写的返回值类型如果⽅法的返回类型是void和基本数据类型,则返回值重写时不可修改。但是如果⽅法的返回值是引⽤类型,重写时是可以返回该引⽤类型的⼦类的。

构造⽅法⽆法被重写,但是可以重载,一个类中可以出现多个构造函数


Java 语言有哪些特点?


1.面向对象

面向对象(OOP)就是Java语言的基础,也是Java语言的重要特性。面向对象的概念:生活中的一切事物都可以被称之为对象,生活中随处可见的事物就是一个对象,我们可以将这些事物的状态特征(属性)以及行为特征(方法)提取并出来,并以固定的形式表示。

2.简单好用

Java语言是由C和C++演变而来的,它省略了C语言中所有的难以理解、容易混淆的特性(比如指针),变得更加严谨、简洁、易使用。

3.健壮性

Java的安全检查机制,将许多程序中的错误扼杀在摇蓝之中。 另外,在Java语言中还具备了许多保证程序稳定、健壮的特性(强类型机制、异常处理、垃圾的自动收集等),有效地减少了错误,使得Java应用程序更加健壮。

4.安全性

Java通常被用在网络环境中,为此,Java提供了一个安全机制以防恶意代码的攻击,从而可以提高系统的安全性。

5.平台无关性

Java平台无关性由Java 虚拟机实现,Java软件可以不受计算机硬件和操作系统的约束而在任意计算机环境下正常运行。

6.支持多线程

在C++ 语言没有内置的多线程机制,因此必须调用操作系统的多线程功能来进行多线程程序设计,而 Java 语言却提供了多线程支持。多线程机制使应用程序在同一时间并行执行多项任务,该机制使得程序能够具有更好的交互性、实时性。

7.分布式(支持网络编程)

Java语言具有强大的、易于使用的网络能力,非常适合开发分布式计算的程序。java中提供了网络应用编程接口(java.net),使得我们可以通过URL、Socket等远程访问对象。

8.编译与解释共存

Java 是编译与解释共存的语言


JDK 、JRE和JVM


在这里插入图片描述

JDK:Java Development Kit 的简称,java 开发工具包,是Sun Microsystems针对Java开发员的产品,提供了 java 的开发环境和运行环境,JDK中包含JRE,在JDK的安装目录中可以找到一个jre的目录。

JRE:Java Runtime Environment 的简称,是运行基于Java语言编写的程序所不可缺少的运行环境。通过它,Java的开发者才得以将自己开发的程序发布到用户手中,让用户使用。在jre文件中有bin和lib文件夹,我们可以认为bin文件夹对应的就是JVM,而lib则对应JVM工作所需要的类库。

JVM:java virtual machine简称,是我们常说的java虚拟机,它是整个java实现跨平台的最核心的部分,所有的java程序会首先被编译为 .class 的类文件(字节码文件),这种类文件可以在虚拟机上执行。JVM屏蔽了与具体操作系统平台相关的信息,使得Java程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。

需要运行 java 程序,只需安装 JRE 就可以了

需要编写 java 程序,需要安装 JDK

字节码文件:

字节码文件是一种可以JVM 上运行的文件(文件扩展名为 .class ),它不⾯向任何特定的处理器,只⾯向虚拟机。Java 语⾔通过字节码的⽅式,在⼀定程度上解决了传统解释型语⾔执⾏效率低的问题,同时⼜保留了解释型语⾔可移植的特点。所以 Java 程序运⾏时比较⾼效,⽽且,由于字节码并不针对⼀种特定的机器,因此,Java 程序⽆须重新编译便可在多种不同操作系统的计算机上运⾏


String、StringBuffer 和 StringBuilder 的区别?


可变性:

String 类中使⽤ final 关键字修饰字符数组来保存字符串,所以 String 对象是不可变的,每次操作都会产生新对象。⽽ StringBuilder 与 StringBuffer 都继承⾃ AbstractStringBuilder 类,在 AbstractStringBuilder 中也是使⽤字符数组保存字符串 char[]value 但是没有⽤ final 关键字修饰,所以这两种对象都是可变的。

线程安全:

String 中的对象是不可变的,也就可以理解为常量,线程安全。StringBuilder 与 StringBuffer 的构造⽅法都是调⽤⽗类构造⽅法也就是 AbstractStringBuilder(其中定义了一些字符串的基本操作,本身是线程安全的) 实现的。StringBuffer 对⽅法加了同步锁或者对调⽤的⽅法加了同步锁(synchronized),所以是线程安全的。StringBuilder 并没有对⽅法进⾏加同步锁,所以是⾮线程安全的。

性能:

每次对 String 类型进⾏改变的时候,都会⽣成⼀个新的 String 对象,然后将指针指向新的 String对象。StringBuffer 每次都会对 StringBuffer 对象本身进⾏操作,⽽不是⽣成新的对象并改变对象引⽤。相同情况下使⽤ StringBuilder 相⽐使⽤ StringBuffer 仅能获得 10%~15% 左右的性能提升,但却要冒多线程不安全的⻛险。

对于三者使⽤的总结:

1. 操作少量的数据: 适⽤ String

2. 单线程操作字符串缓冲区下操作⼤量数据: 适⽤ StringBuilder

3. 多线程操作字符串缓冲区下操作⼤量数据: 适⽤ StringBuffer

String 为什么是不可变的?

接口与抽象类的区别?


抽象类:如果一个类里有抽象方法,那么这个类只能是抽象类,抽象类里可以没有抽象方法,抽象方法只能申明,不能实现。

接口:在Java中接口就是一个规范,是一种更加抽象化的抽象类。需要被类实现。

两者区别:

  • ⼀个类可以实现多个接⼝,但只能实现⼀个抽象类。接⼝本身也可以继承接口进行扩展。

  • 接⼝中只能定义公共的静态常量,不能有其他变量,⽅法默认是 public ,所有⽅法在接⼝中不能有实现(Java 8 开始接口⽅法可以有默认实现);抽象类中可以定义普通变量,抽象方法需要被实现,不能是静态的,也不能是私有的,可以使用public 、 protected 和 default 这些修饰符修饰。

  • 抽象类里的抽象方法必须全部被子类所实现,如果子类不能全部实现父类抽象方法,那么该子类只能是抽象类。同样,一个实现接口的时候,如不能全部实现接口方法,那么该类也只能为抽象类。

  • 从设计层⾯来说,抽象是对类的抽象,是⼀种模板设计(is-a),⽽接⼝是对⾏为的抽象,是⼀种⾏为的规范(like-a)。

相同点:

抽象类和接口都不能直接实例化,如果要实例化,抽象类变量必须指向实现所有抽象方法的子类对象,接口变量必须指向实现所有接口方法的类对象。


成员变量与局部变量的区别有哪些?


  1. 从语法形式上看:成员变量是属于类的,⽽局部变量是在⽅法中定义的变量或是⽅法的参数;成员变量可以被 public , private , static 等修饰符所修饰,⽽局部变量不能被访问控制修饰符及 static 所修饰;但是,成员变量和局部变量都能被 final 所修饰。

  2. 从变量在内存中的存储⽅式来看:如果成员变量是使⽤ static 修饰的,那么这个成员变量是属于类的,如果没有使⽤ static 修饰,这个成员变量是属于实例的。对象存于堆内存,如果局部变量类型为基本数据类型,那么存储在栈内存,如果为引⽤数据类型,那存放的是指向堆内存对象的引⽤或者是指向常量池中的地址。

  3. 从变量在内存中的⽣存时间上看:成员变量是对象的⼀部分,它随着对象的创建⽽存在,⽽局部变量随着⽅法的调⽤⽽⾃动消失。

  4. 成员变量如果没有被赋初值:则会⾃动以类型的默认值⽽赋值(⼀种情况例外:被 final 修饰的成员变量也必须显式地赋值),⽽局部变量则不会⾃动赋值。


==与equals的区别?


  • == : 比较两个对象是否相等,本质是比较两者的值是否相等,对于基本数据类型来说,==比较的是值。对于引用数据类型来说,==比较的是对象的内存地址(因为引用类型变量存的值是对象的地址)。

  • equals() : 它的作⽤不能用于判断基本数据类型的变量,只能用来判断两个对象是否相等。但它⼀般有两种使⽤情况:

  • 情况 1:类没有覆盖 equals() ⽅法。则通过 equals() 比较该类的两个对象时,等价于通过“==”比较这两个对象。

  • 情况 2:类覆盖了 equals() ⽅法。⼀般,我们都覆盖 equals() ⽅法来比较两个对象的内容是否相等;若它们的内容相等,则返回 true (即,认为这两个对象相等)。

以String为例:

String 中的 equals ⽅法是被重写过的,因为 object 的 equals ⽅法是比较的对象的内存地址,⽽ String 的 equals ⽅法比较的是对象的值。当创建 String 类型的对象时,虚拟机会在常量池中查找有没有已经存在的值和要创建的值相同的对象,如果有就把它赋给当前引⽤。如果没有就在常量池中重新创建⼀个 String 对象。

在这里插入图片描述例题:

在这里插入图片描述


hashCode 与 equals


hashCode()介绍:

  • hashCode() 的作⽤是获取哈希码,也称为散列码;它实际上是返回⼀个 int 整数。这个哈希码的作⽤是确定该对象在哈希表中的索引位置。 hashCode() 定义在 JDK 的 Object.java中,这就意味着 Java 中的任何类都包含有 hashCode() 函数。Object 的 hashcode ⽅法是本地⽅法,也就是⽤ c 语⾔或 c++ 实现的,该⽅法通常⽤来将对象的 内存地址 转换为整数之后返回。

  • 散列表存储的是键值对(key-value),它的特点是:能根据“键”快速的检索出对应的“值”。这其中就利⽤到了散列码!(可以快速找到所需要的对象)

为什么要有 hashCode?

  • 以“ HashSet 如何检查重复”为例⼦来说明为什么要有 hashCode?

当对象加⼊ HashSet 时, HashSet 会先计算对象的 hashcode 值来判断对象加⼊的位置,同时也会与其他已经加⼊的对象的 hashcode 值作比较,如果没有相符的 hashcode, HashSet会假设对象没有重复出现。但是如果发现有相同 hashcode 值的对象,这时会调⽤ equals() ⽅法来检查 hashcode 相等的对象是否真的相同。如果两者相同, HashSet 就不会让其加⼊操作成功。如果不同的话,就会重新散列到其他位置。这样我们就⼤⼤减少了 equals 的次数,相应就⼤⼤提⾼了执⾏速度。

为什么重写 equals 时必须重写 hashCode ⽅法?

  • 如果两个对象相等,则 hashcode ⼀定也是相同的。

  • 两个对象相等,对两个对象分别调⽤ equals⽅法都返回 true。

  • 但是,两个对象有相同的 hashcode 值,它们也不⼀定是相等的 。

  • 因此,equals ⽅法被覆盖过,则 hashCode ⽅法也必须被覆盖。

  • hashCode() 的默认⾏为是对堆上的对象产⽣独特值。如果没有重写 hashCode() ,则该class 的两个对象⽆论如何都不会相等(即使这两个对象指向相同的数据)

为什么两个对象有相同的 hashcode 值,它们也不⼀定是相等的?

  • 因为 hashCode() 所使⽤的杂凑算法也许刚好会让多个对象传回相同的杂凑值。越糟糕的杂凑算法越容易碰撞,但这也与数据值域分布的特性有关(所谓碰撞也就是指的是不同的对象得到相同的 hashCode) 。

  • 我们刚刚也提到了 HashSet ,如果 HashSet 在对⽐的时候,同样的 hashcode 有多个对象,它会使⽤ equals() 来判断是否真的相同。也就是说 hashcode 只是⽤来缩⼩查找成本。


final关键字


final 关键字,意思是最终的、不可修改的,最见不得变化 ,用来修饰类、方法和变量,具有以下特点:

  • 修饰类:类不能继承,final 类中的所有成员方法都会被隐式的指定为 final 方法;

  • 修饰符变量:该变量为常量,,如果是基本数据类型的变量,则其数值一旦在初始化之后便不能更改;如果是引用类型的变量,则在对其初始化之后便不能让其指向另一个对象。

  • **修饰符方法:方法不能重写

说明:使用 final 方法的原因有两个。第一个原因是把方法锁定,以防任何继承类修改它的含义;第二个原因是效率。在早期的 Java 实现版本中,会将 final 方法转为内嵌调用。但是如果方法过于庞大,可能看不到内嵌调用带来的任何性能提升(现在的 Java 版本已经不需要使用 final 方法进行这些优化了)。类中所有的 private 方法都隐式地指定为 final。**

在这里插入图片描述


final、finally、finalize 有什么区别?


final可以修饰类,变量,方法,修饰的类不能被继承,修饰的变量不能重新赋值,修饰的方法不能被重写

finally一般作用在try-catch代码块中,finally代码块内语句无论是否发生异常,都会在执行finally,常用于一些流的关闭。( 可以在try 或 finally 块中使用 System.exit(int) 退出程序,使finally不执行)

finalize:Object类的一个方法,Java 中允许使用 finalize()方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。


java 中都有哪些引用类型?


强、软、弱、虚

  • 强引用(StrongReference): 最传统的“引用”的定义,是指在程序代码之中普遍存在的引用赋值,即类似“object obj=new Object()”这种引用关系。无论任何情况下,只要强引用关系还存在,垃圾收集器就永远不会回收掉被引用的对象。

  • 软引用(SoftReference): 在系统将要发生内存溢出之前,将会把这些对象列入回收范围之中进行第二次回收。如果这次回收后还没有足够的内存,才会抛出内存流出异常。

  • 弱引用(WeakReference): 被弱引用关联的对象只能生存到下一次垃圾收集之前。当垃圾收集器工作时,无论内存空间是否足够,都会回收掉被弱引用关联的对象。

  • 虚引用(PhantomReference): 一个对象是否有虚引用的存在,完全不会对其生存时间构成影响,也无法通过虚引用来获得一个对


实例化对象有哪几种方式?

最后总结

ActiveMQ+Kafka+RabbitMQ学习笔记PDF

image.png

  • RabbitMQ实战指南

image.png

  • 手写RocketMQ笔记

image.png

  • 手写“Kafka笔记”

image

关于分布式,限流+缓存+缓存,这三大技术(包含:ZooKeeper+Nginx+MongoDB+memcached+Redis+ActiveMQ+Kafka+RabbitMQ)等等。这些相关的面试也好,还有手写以及学习的笔记PDF,都是啃透分布式技术必不可少的宝藏。以上的每一个专题每一个小分类都有相关的介绍,并且小编也已经将其整理成PDF啦

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Java)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
手写“Kafka笔记”

[外链图片转存中…(img-WKGbsIlK-1713557367975)]

关于分布式,限流+缓存+缓存,这三大技术(包含:ZooKeeper+Nginx+MongoDB+memcached+Redis+ActiveMQ+Kafka+RabbitMQ)等等。这些相关的面试也好,还有手写以及学习的笔记PDF,都是啃透分布式技术必不可少的宝藏。以上的每一个专题每一个小分类都有相关的介绍,并且小编也已经将其整理成PDF啦

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Java)
[外链图片转存中…(img-PeJpZAWL-1713557367975)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 21
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值