Java 基础高频面试题(2024年最新版),阿里巴巴面试会问的问题及答案

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

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

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

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

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

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

正文

1、面向对象的三个基本特征?

面向对象的三个基本特征是:封装、继承和多态。

继承:让某个类型的对象获得另一个类型的对象的属性的方法。继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。

封装:隐藏部分对象的属性和实现细节,对数据的访问只能通过外公开的接口。通过这种方式,对象对内部数据提供了不同级别的保护,以防止程序中无关的部分意外的改变或错误的使用了对象的私有部分。

多态:对于同一个行为,不同的子类对象具有不同的表现形式。多态存在的3个条件:1)继承;2)重写;3)父类引用指向子类对象。

举个简单的例子:英雄联盟里面我们按下 Q 键这个动作:

  • 对于亚索,就是斩钢闪

  • 对于提莫,就是致盲吹箭

  • 对于剑圣,就是阿尔法突袭

同一个事件发生在不同的对象上会产生不同的结果。

我再举一个简单的例子帮助大家理解,这个例子可能不是完全准确,但是我认为是有利于理解的。

public class Animal { // 动物

public void sleep() {

System.out.println(“躺着睡”);

}

}

class Horse extends Animal { // 马 是一种动物

public void sleep() {

System.out.println(“站着睡”);

}

}

class Cat extends Animal { // 猫 是一种动物

private int age;

public int getAge() {

return age + 1;

}

@Override

public void sleep() {

System.out.println(“四脚朝天的睡”);

}

}

在这个例子中:

House 和 Cat 都是 Animal,所以他们都继承了 Animal,同时也从 Animal 继承了 sleep 这个行为。

但是针对 sleep 这个行为,House 和 Cat 进行了重写,有了不同的表现形式(实现),这个我们称为多态。

在 Cat 里,将 age 属性定义为 private,外界无法直接访问,要获取 Cat 的 age 信息只能通过 getAge 方法,从而对外隐藏了 age 属性,这个就叫做封装。当然,这边 age 只是个例子,实际使用中可能是一个复杂很多的对象。

2、访问修饰符public,private,protected,以及不写时的区别?

3、下面两个代码块能正常编译和执行吗?

// 代码块1

short s1 = 1; s1 = s1 + 1;

// 代码块2

short s1 = 1; s1 += 1;

代码块1编译报错,错误原因是:不兼容的类型: 从int转换到short可能会有损失”。

代码块2正常编译和执行。

我们将代码块2进行编译,字节码如下:

public class com.joonwhee.open.demo.Convert {

public com.joonwhee.open.demo.Convert();

Code:

0: aload_0

1: invokespecial #1 // Method java/lang/Object.“”😦)V

4: return

public static void main(java.lang.String[]);

Code:

0: iconst_1 // 将int类型值1入(操作数)栈

1: istore_1 // 将栈顶int类型值保存到局部变量1中

2: iload_1 // 从局部变量1中装载int类型值入栈

3: iconst_1 // 将int类型值1入栈

4: iadd // 将栈顶两int类型数相加,结果入栈

5: i2s // 将栈顶int类型值截断成short类型值,后带符号扩展成int类型值入栈。

6: istore_1 // 将栈顶int类型值保存到局部变量1中

7: return

}

可以看到字节码中包含了 i2s 指令,该指令用于将 int 转成 short。i2s 是 int to short 的缩写。

其实,s1 += 1 相当于 s1 = (short)(s1 + 1),有兴趣的可以自己编译下这两行代码的字节码,你会发现是一摸一样的。

说好的 Java 基础题,怎么又开始变态起来了???

4、基础考察,指出下题的输出结果

public static void main(String[] args) {

Integer a = 128, b = 128, c = 127, d = 127;

System.out.println(a == b);

System.out.println(c == d);

}

答案是:false,true。

执行 Integer a = 128,相当于执行:Integer a = Integer.valueOf(128),基本类型自动转换为包装类的过程称为自动装箱(autoboxing)。

public static Integer valueOf(int i) {

if (i >= IntegerCache.low && i <= IntegerCache.high)

return IntegerCache.cache[i + (-IntegerCache.low)];

return new Integer(i);

}

在 Integer 中引入了 IntegerCache 来缓存一定范围的值,IntegerCache 默认情况下范围为:-128~127。

本题中的 127 命中了 IntegerCache,所以 c 和 d 是相同对象,而 128 则没有命中,所以 a 和 b 是不同对象。

但是这个缓存范围时可以修改的,可能有些人不知道。可以通过JVM启动参数:-XX:AutoBoxCacheMax= 来修改上限值,如下图所示:

5、用最有效率的方法计算2乘以8?

2 << 3。

进阶:通常情况下,可以认为位运算是性能最高的。但是,其实编译器现在已经“非常聪明了”,很多指令编译器都能自己做优化。所以在实际实用中,我们无需特意去追求实用位运算,这样不仅会导致代码可读性很差,而且某些自作聪明的优化反而会误导编译器,使得编译器无法进行更好的优化。

这可能就是所谓的“猪队友”吧。

6、&和&&的区别?

&&:逻辑与运算符。当运算符左右两边的表达式都为 true,才返回 true。同时具有短路性,如果第一个表达式为 false,则直接返回 false。

&:逻辑与运算符、按位与运算符。

按位与运算符:用于二进制的计算,只有对应的两个二进位均为1时,结果位才为1 ,否则为0。

逻辑与运算符:& 在用于逻辑与时,和 && 的区别是不具有短路性。所在通常使用逻辑与运算符都会使用 &&,而 & 更多的适用于位运算。

7、String 是 Java 基本数据类型吗?

答:不是。Java 中的基本数据类型只有8个:byte、short、int、long、float、double、char、boolean;除了基本类型(primitive type),剩下的都是引用类型(reference type)。

基本数据类型:数据直接存储在栈上

引用数据类型区别:数据存储在堆上,栈上只存储引用地址

8、String 类可以继承吗?

不行。String 类使用 final 修饰,无法被继承。

9、String和StringBuilder、StringBuffer的区别?

String:String 的值被创建后不能修改,任何对 String 的修改都会引发新的 String 对象的生成。

StringBuffer:跟 String 类似,但是值可以被修改,使用 synchronized 来保证线程安全。

StringBuilder:StringBuffer 的非线程安全版本,没有使用 synchronized,具有更高的性能,推荐优先使用。

10、String s = new String(“xyz”) 创建了几个字符串对象?

一个或两个。如果字符串常量池已经有“xyz”,则是一个;否则,两个。

当字符创常量池没有 “xyz”,此时会创建如下两个对象:

一个是字符串字面量 “xyz” 所对应的、驻留(intern)在一个全局共享的字符串常量池中的实例,此时该实例也是在堆中,字符串常量池只放引用。

另一个是通过 new String() 创建并初始化的,内容与"xyz"相同的实例,也是在堆中。

11、String s = “xyz” 和 String s = new String(“xyz”) 区别?

两个语句都会先去字符串常量池中检查是否已经存在 “xyz”,如果有则直接使用,如果没有则会在常量池中创建 “xyz” 对象。

另外,String s = new String(“xyz”) 还会通过 new String() 在堆里创建一个内容与 “xyz” 相同的对象实例。

所以前者其实理解为被后者的所包含。

12、== 和 equals 的区别是什么?

==:运算符,用于比较基础类型变量和引用类型变量。

对于基础类型变量,比较的变量保存的值是否相同,类型不一定要相同。

short s1 = 1; long l1 = 1;

// 结果:true。类型不同,但是值相同

System.out.println(s1 == l1);

对于引用类型变量,比较的是两个对象的地址是否相同。

Integer i1 = new Integer(1);

Integer i2 = new Integer(1);

// 结果:false。通过new创建,在内存中指向两个不同的对象

System.out.println(i1 == i2);

equals:Object 类中定义的方法,通常用于比较两个对象的值是否相等。

equals 在 Object 方法中其实等同于 ==,但是在实际的使用中,equals 通常被重写用于比较两个对象的值是否相同。

Integer i1 = new Integer(1);

Integer i2 = new Integer(1);

// 结果:true。两个不同的对象,但是具有相同的值

System.out.println(i1.equals(i2));

// Integer的equals重写方法

public boolean equals(Object obj) {

if (obj instanceof Integer) {

// 比较对象中保存的值是否相同

return value == ((Integer)obj).intValue();

}

return false;

}

13、两个对象的 hashCode() 相同,则 equals() 也一定为 true,对吗?

不对。hashCode() 和 equals() 之间的关系如下:

当有 a.equals(b) == true 时,则 a.hashCode() == b.hashCode() 必然成立,

反过来,当 a.hashCode() == b.hashCode() 时,a.equals(b) 不一定为 true。

14、什么是反射

反射是指在运行状态中,对于任意一个类都能够知道这个类所有的属性和方法;并且对于任意一个对象,都能够调用它的任意一个方法;这种动态获取信息以及动态调用对象方法的功能称为反射机制。

15、深拷贝和浅拷贝区别是什么?

数据分为基本数据类型和引用数据类型。基本数据类型:数据直接存储在栈中;引用数据类型:存储在栈中的是对象的引用地址,真实的对象数据存放在堆内存里。

浅拷贝:对于基础数据类型:直接复制数据值;对于引用数据类型:只是复制了对象的引用地址,新旧对象指向同一个内存地址,修改其中一个对象的值,另一个对象的值随之改变。

深拷贝:对于基础数据类型:直接复制数据值;对于引用数据类型:开辟新的内存空间,在新的内存空间里复制一个一模一样的对象,新老对象不共享内存,修改其中一个对象的值,不会影响另一个对象。

深拷贝相比于浅拷贝速度较慢并且花销较大。

16、并发和并行有什么区别?

并发:两个或多个事件在同一时间间隔发生。

并行:两个或者多个事件在同一时刻发生。

并行是真正意义上,同一时刻做多件事情,而并发在同一时刻只会做一件事件,只是可以将时间切碎,交替做多件事情。

网上有个例子挺形象的:

你吃饭吃到一半,电话来了,你一直到吃完了以后才去接,这就说明你不支持并发也不支持并行。

你吃饭吃到一半,电话来了,你停了下来接了电话,接完后继续吃饭,这说明你支持并发。

你吃饭吃到一半,电话来了,你一边打电话一边吃饭,这说明你支持并行。

17、构造器是否可被 重写?

Constructor 不能被 override(重写),但是可以 overload(重载),所以你可以看到⼀个类中有多个构造函数的情况。

18、当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?

值传递。Java 中只有值传递,对于对象参数,值的内容是对象的引用。

19、Java 静态变量和成员变量的区别。

public class Demo {

/**

  • 静态变量:又称类变量,static修饰

*/

public static String STATIC_VARIABLE = “静态变量”;

/**

  • 实例变量:又称成员变量,没有static修饰

*/

public String INSTANCE_VARIABLE = “实例变量”;

}

成员变量存在于堆内存中。静态变量存在于方法区中。

成员变量与对象共存亡,随着对象创建而存在,随着对象被回收而释放。静态变量与类共存亡,随着类的加载而存在,随着类的消失而消失。

成员变量所属于对象,所以也称为实例变量。静态变量所属于类,所以也称为类变量。

成员变量只能被对象所调用 。静态变量可以被对象调用,也可以被类名调用。

20、是否可以从一个静态(static)方法内部发出对非静态(non-static)方法的调用?

区分两种情况,发出调用时是否显示创建了对象实例。

1)没有显示创建对象实例:不可以发起调用,非静态方法只能被对象所调用,静态方法可以通过对象调用,也可以通过类名调用,所以静态方法被调用时,可能还没有创建任何实例对象。因此通过静态方法内部发出对非静态方法的调用,此时可能无法知道非静态方法属于哪个对象。

public class Demo {

public static void staticMethod() {

// 直接调用非静态方法:编译报错

instanceMethod();

}

public void instanceMethod() {

System.out.println(“非静态方法”);

}

}

2)显示创建对象实例:可以发起调用,在静态方法中显示的创建对象实例,则可以正常的调用。

public class Demo {

public static void staticMethod() {

// 先创建实例对象,再调用非静态方法:成功执行

Demo demo = new Demo();

demo.instanceMethod();

}

public void instanceMethod() {

System.out.println(“非静态方法”);

}

}

21、初始化考察,请指出下面程序的运行结果。

public class InitialTest {

public static void main(String[] args) {

A ab = new B();

ab = new B();

}

}

class A {

static { // 父类静态代码块

System.out.print(“A”);

}

public A() { // 父类构造器

System.out.print(“a”);

}

}

class B extends A {

static { // 子类静态代码块

System.out.print(“B”);

}

public B() { // 子类构造器

System.out.print(“b”);

}

}

执行结果:ABabab,两个考察点:

1)静态变量只会初始化(执行)一次。

2)当有父类时,完整的初始化顺序为:父类静态变量(静态代码块)->子类静态变量(静态代码块)->父类非静态变量(非静态代码块)->父类构造器 ->子类非静态变量(非静态代码块)->子类构造器 。

关于初始化,这题算入门题,我之前还写过一道有(fei)点(chang)意(bian)思(tai)的进阶题目,有兴趣的可以看看:一道有意思的“初始化”面试题

22、重载(Overload)和重写(Override)的区别?

方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性。

重载:一个类中有多个同名的方法,但是具有有不同的参数列表(参数类型不同、参数个数不同或者二者都不同)。

重写:发生在子类与父类之间,子类对父类的方法进行重写,参数都不能改变,返回值类型可以不相同,但是必须是父类返回值的派生类。即外壳不变,核心重写!重写的好处在于子类可以根据需要,定义特定于自己的行为。

23、为什么不能根据返回类型来区分重载?

如果我们有两个方法如下,当我们调用:test(1) 时,编译器无法确认要调用的是哪个。

// 方法1

int test(int a);

// 方法2

long test(int a);

方法的返回值只是作为方法运行之后的一个“状态”,但是并不是所有调用都关注返回值,所以不能将返回值作为重载的唯一区分条件。

24、抽象类(abstract class)和接口(interface)有什么区别?

抽象类只能单继承,接口可以多实现。

抽象类可以有构造方法,接口中不能有构造方法。

抽象类中可以有成员变量,接口中没有成员变量,只能有常量(默认就是 public static final)

抽象类中可以包含非抽象的方法,在 Java 7 之前接口中的所有方法都是抽象的,在 Java 8 之后,接口支持非抽象方法:default 方法、静态方法等。Java 9 支持私有方法、私有静态方法。

抽象类中的抽象方法类型可以是任意修饰符,Java 8 之前接口中的方法只能是 public 类型,Java 9 支持 private 类型。

设计思想的区别:

接口是自上而下的抽象过程,接口规范了某些行为,是对某一行为的抽象。我需要这个行为,我就去实现某个接口,但是具体这个行为怎么实现,完全由自己决定。

抽象类是自下而上的抽象过程,抽象类提供了通用实现,是对某一类事物的抽象。我们在写实现类的时候,发现某些实现类具有几乎相同的实现,因此我们将这些相同的实现抽取出来成为抽象类,然后如果有一些差异点,则可以提供抽象方法来支持自定义实现。

我在网上看到有个说法,挺形象的:

普通类像亲爹 ,他有啥都是你的。

抽象类像叔伯,有一部分会给你,还能指导你做事的方法。

接口像干爹,可以给你指引方法,但是做成啥样得你自己努力实现。

25、Error 和 Exception 有什么区别?

Error 和 Exception 都是 Throwable 的子类,用于表示程序出现了不正常的情况。区别在于:

Error 表示系统级的错误和程序不必处理的异常,是恢复不是不可能但很困难的情况下的一种严重问题,比如内存溢出,不可能指望程序能处理这样的情况。

Exception 表示需要捕捉或者需要程序进行处理的异常,是一种设计或实现问题,也就是说,它表示如果程序运行正常,从不会发生的情况。

26、Java 中的 final 关键字有哪些用法?

修饰类:该类不能再派生出新的子类,不能作为父类被继承。因此,一个类不能同时被声明为abstract 和 final。

修饰方法:该方法不能被子类重写。

修饰变量:该变量必须在声明时给定初值,而在以后只能读取,不可修改。 如果变量是对象,则指的是引用不可修改,但是对象的属性还是可以修改的。

public class FinalDemo {

// 不可再修改该变量的值

public static final int FINAL_VARIABLE = 0;

// 不可再修改该变量的引用,但是可以直接修改属性值

public static final User USER = new User();

public static void main(String[] args) {

// 输出:User(id=0, name=null, age=0)

System.out.println(USER);

// 直接修改属性值

USER.setName(“test”);

// 输出:User(id=0, name=test, age=0)

System.out.println(USER);

}

}

27、阐述 final、finally、finalize 的区别。

其实是三个完全不相关的东西,只是长的有点像。。

final 如上所示。

finally:finally 是对 Java 异常处理机制的最佳补充,通常配合 try、catch 使用,用于存放那些无论是否出现异常都一定会执行的代码。在实际使用中,通常用于释放锁、数据库连接等资源,把资源释放方法放到 finally 中,可以大大降低程序出错的几率。

finalize:Object 中的方法,在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。finalize()方法仅作为了解即可,在 Java 9 中该方法已经被标记为废弃,并添加新的 java.lang.ref.Cleaner,提供了更灵活和有效的方法来释放资源。这也侧面说明了,这个方法的设计是失败的,因此更加不能去使用它。

28、try、catch、finally 考察,请指出下面程序的运行结果。

public class TryDemo {

public static void main(String[] args) {

System.out.println(test());

}

public static int test() {

try {

return 1;

} catch (Exception e) {

return 2;

} finally {

System.out.print(“3”);

}

}

}

执行结果:31。

相信很多同学应该都做对了,try、catch。finally 的基础用法,在 return 前会先执行 finally 语句块,所以是先输出 finally 里的 3,再输出 return 的 1。

29、try、catch、finally 考察2,请指出下面程序的运行结果。

public class TryDemo {

public static void main(String[] args) {

System.out.println(test1());

}

public static int test1() {

try {

return 2;

} finally {

return 3;

}

}

}

执行结果:3。

这题有点先将,但也不难,try 返回前先执行 finally,结果 finally 里不按套路出牌,直接 return 了,自然也就走不到 try 里面的 return 了。

finally 里面使用 return 仅存在于面试题中,实际开发中千万不要这么用。

30、try、catch、finally 考察3,请指出下面程序的运行结果。

public class TryDemo {

public static void main(String[] args) {

System.out.println(test1());

}

public static int test1() {

int i = 0;

try {

i = 2;

return i;

} finally {

i = 3;

}

}

}

执行结果:2。

这边估计有不少同学会以为结果应该是 3,因为我们知道在 return 前会执行 finally,而 i 在 finally 中被修改为 3 了,那最终返回 i 不是应该为 3 吗?确实很容易这么想,我最初也是这么想的,当初的自己还是太年轻了啊。

这边的根本原因是,在执行 finally 之前,JVM 会先将 i 的结果暂存起来,然后 finally 执行完毕后,会返回之前暂存的结果,而不是返回 i,所以即使这边 i 已经被修改为 3,最终返回的还是之前暂存起来的结果 2。

这边其实根据字节码可以很容易看出来,在进入 finally 之前,JVM 会使用 iload、istore 两个指令,将结果暂存,在最终返回时在通过 iload、ireturn 指令返回暂存的结果。

为了避免气氛再次变态起来,我这边就不贴具体的字节码程序了,有兴趣的同学可以自己编译查看下。

31、JDK1.8之后有哪些新特性?

接口默认方法:Java 8允许我们给接口添加一个非抽象的方法实现,只需要使用 default关键字即可

Lambda 表达式和函数式接口:Lambda 表达式本质上是一段匿名内部类,也可以是一段可以传递的代码。Lambda 允许把函数作为一个方法的参数(函数作为参数传递到方法中),使用 Lambda 表达式使代码更加简洁,但是也不要滥用,否则会有可读性等问题,《Effective Java》作者 Josh Bloch 建议使用 Lambda 表达式最好不要超过3行。

Stream API:用函数式编程方式在集合类上进行复杂操作的工具,配合Lambda表达式可以方便的对集合进行处理。Java8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用Stream API 对集合数据进行操作,就类似于使用 SQL 执行的数据库查询。也可以使用 Stream API 来并行执行操作。简而言之,Stream API 提供了一种高效且易于使用的处理数据的方式。

方法引用:方法引用提供了非常有用的语法,可以直接引用已有Java类或对象(实例)的方法或构造器。与lambda联合使用,方法引用可以使语言的构造更紧凑简洁,减少冗余代码。

日期时间API:Java 8 引入了新的日期时间API改进了日期时间的管理。

Optional 类:著名的 NullPointerException 是引起系统失败最常见的原因。很久以前 Google Guava 项目引入了 Optional 作为解决空指针异常的一种方式,不赞成代码被 null 检查的代码污染,期望程序员写整洁的代码。受Google Guava的鼓励,Optional 现在是Java 8库的一部分。

新工具:新的编译工具,如:Nashorn引擎 jjs、 类依赖分析器 jdeps。

50、wait() 和 sleep() 方法的区别

来源不同:sleep() 来自 Thread 类,wait() 来自 Object 类。

对于同步锁的影响不同:sleep() 不会该表同步锁的行为,如果当前线程持有同步锁,那么 sleep 是不会让线程释放同步锁的。wait() 会释放同步锁,让其他线程进入 synchronized 代码块执行。

使用范围不同:sleep() 可以在任何地方使用。wait() 只能在同步控制方法或者同步控制块里面使用,否则会抛 IllegalMonitorStateException。

恢复方式不同:两者会暂停当前线程,但是在恢复上不太一样。sleep() 在时间到了之后会重新恢复;wait() 则需要其他线程调用同一对象的 notify()/nofityAll() 才能重新恢复。

51、线程的 sleep() 方法和 yield() 方法有什么区别?

线程执行 sleep() 方法后进入超时等待(TIMED_WAITING)状态,而执行 yield() 方法后进入就绪(READY)状态。

sleep() 方法给其他线程运行机会时不考虑线程的优先级,因此会给低优先级的线程运行的机会;yield() 方法只会给相同优先级或更高优先级的线程以运行的机会。

52、线程的 join() 方法是干啥用的?

用于等待当前线程终止。如果一个线程A执行了 threadB.join() 语句,其含义是:当前线程A等待 threadB 线程终止之后才从 threadB.join() 返回继续往下执行自己的代码。

53、编写多线程程序有几种实现方式?

通常来说,可以认为有三种方式:1)继承 Thread 类;2)实现 Runnable 接口;3)实现 Callable 接口。

其中,Thread 其实也是实现了 Runable 接口。Runnable 和 Callable 的主要区别在于是否有返回值。

54、Thread 调用 start() 方法和调用 run() 方法的区别

run():普通的方法调用,在主线程中执行,不会新建一个线程来执行。

总结:绘上一张Kakfa架构思维大纲脑图(xmind)

image

其实关于Kafka,能问的问题实在是太多了,扒了几天,最终筛选出44问:基础篇17问、进阶篇15问、高级篇12问,个个直戳痛点,不知道如果你不着急看答案,又能答出几个呢?

若是对Kafka的知识还回忆不起来,不妨先看我手绘的知识总结脑图(xmind不能上传,文章里用的是图片版)进行整体架构的梳理

梳理了知识,刷完了面试,如若你还想进一步的深入学习解读kafka以及源码,那么接下来的这份《手写“kafka”》将会是个不错的选择。

  • Kafka入门

  • 为什么选择Kafka

  • Kafka的安装、管理和配置

  • Kafka的集群

  • 第一个Kafka程序

  • Kafka的生产者

  • Kafka的消费者

  • 深入理解Kafka

  • 可靠的数据传递

  • Spring和Kafka的整合

  • SpringBoot和Kafka的整合

  • Kafka实战之削峰填谷

  • 数据管道和流式处理(了解即可)

image

image

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

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

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
义是:当前线程A等待 threadB 线程终止之后才从 threadB.join() 返回继续往下执行自己的代码。

53、编写多线程程序有几种实现方式?

通常来说,可以认为有三种方式:1)继承 Thread 类;2)实现 Runnable 接口;3)实现 Callable 接口。

其中,Thread 其实也是实现了 Runable 接口。Runnable 和 Callable 的主要区别在于是否有返回值。

54、Thread 调用 start() 方法和调用 run() 方法的区别

run():普通的方法调用,在主线程中执行,不会新建一个线程来执行。

总结:绘上一张Kakfa架构思维大纲脑图(xmind)

[外链图片转存中…(img-ksuPE2Tr-1713386014594)]

其实关于Kafka,能问的问题实在是太多了,扒了几天,最终筛选出44问:基础篇17问、进阶篇15问、高级篇12问,个个直戳痛点,不知道如果你不着急看答案,又能答出几个呢?

若是对Kafka的知识还回忆不起来,不妨先看我手绘的知识总结脑图(xmind不能上传,文章里用的是图片版)进行整体架构的梳理

梳理了知识,刷完了面试,如若你还想进一步的深入学习解读kafka以及源码,那么接下来的这份《手写“kafka”》将会是个不错的选择。

  • Kafka入门

  • 为什么选择Kafka

  • Kafka的安装、管理和配置

  • Kafka的集群

  • 第一个Kafka程序

  • Kafka的生产者

  • Kafka的消费者

  • 深入理解Kafka

  • 可靠的数据传递

  • Spring和Kafka的整合

  • SpringBoot和Kafka的整合

  • Kafka实战之削峰填谷

  • 数据管道和流式处理(了解即可)

[外链图片转存中…(img-qK0qASqX-1713386014595)]

[外链图片转存中…(img-vBEseQIn-1713386014595)]

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

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

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

  • 21
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 1. Java中的基本数据类型有哪些?它们的大小是多少? 答:Java中的基本数据类型有byte、short、int、long、float、double、char和boolean。它们的大小分别为8位、16位、32位、64位、32位、64位、16位和1位。 2. Java中的访修饰符有哪些?它们分别代表什么意思? 答:Java中的访修饰符有public、protected、default和private。它们分别代表公开的、受保护的、默认的和私有的。 3. Java中的final关键字有什么作用? 答:final关键字可以用来修饰类、方法和变量。它的作用是使被修饰的类、方法或变量不可被继承、重写或修改。 4. Java中的static关键字有什么作用? 答:static关键字可以用来修饰类、方法和变量。它的作用是使被修饰的类、方法或变量在内存中只有一份拷贝,可以直接通过类名访。 5. Java中的抽象类和接口有什么区别? 答:抽象类和接口都是用来实现多态的机制。抽象类可以包含抽象方法和非抽象方法,可以有构造方法和成员变量,不能被实例化。接口只能包含抽象方法和常量,不能有构造方法和成员变量,可以被多个类实现。 6. Java中的重载和重写有什么区别? 答:重载是指在同一个类中定义多个方法,它们的方法名相同但参数列表不同。重写是指子类重写父类的方法,方法名和参数列表都相同。 7. Java中的异常处理机制是什么? 答:Java中的异常处理机制是通过try-catch-finally语句块来实现的。当程序出现异常时,抛出一个异常对象,可以通过catch语句捕获并处理异常,finally语句块中的代码在try或catch语句块执行完毕后执行。 8. Java中的线程是什么?如何创建线程? 答:线程是程序执行的最小单位,可以同时执行多个线程实现并发执行。可以通过继承Thread类或实现Runnable接口来创建线程,然后调用start()方法启动线程。 9. Java中的集合框架有哪些?它们的区别是什么? 答:Java中的集合框架包括List、Set、Map和Queue等。它们的区别在于List是有序的、可重复的集合,Set是无序的、不可重复的集合,Map是键值对的集合,Queue是队列集合。 10. Java中的反射机制是什么?如何使用反射? 答:Java中的反射机制是指在运行时动态获取类的信息和调用类的方法。可以通过Class类的实例来获取类的信息,然后使用反射API来调用类的方法。使用反射可以实现动态加载类、动态创建对象、动态调用方法等功能。 ### 回答2: Java作为一门广泛应用于软件开发的编程语言,被越来越多的公司和企业所采用。因此,Java开发工程师也成为各大公司中的热门职位之一。为了能够通过Java开发工程师的面试,我们需要对Java基础知识进行深入学习。以下是Java基础高频面试题(2021最新版)。 1. Java语言的特性? Java语言有四个特点,分别是: 1.1 简单性:Java语言的设计非常简单,易于使用和学习,减少了语言的复杂度。 1.2 面向对象:Java语言支持面向对象的编程方式,有助于代码的重用性和维护性。 1.3 平台无关性:Java语言可以在不同的平台上运行,具有跨平台的特性。 1.4 安全性:在Java语言中,提供了许多安全机制,如类的访控制、安全管理器等,能够保证程序的安全性和正确性。 2. Java中包是什么? Java中的包是一种组织程序的方式,它能够将相关的类、接口和其他文件组织在一起,形成一个层次结构。Java中的包有助于代码的重用性和可维护性。 3. Java语言的数据类型有哪些? Java语言支持的数据类型包括: 3.1 基本数据类型:byte、short、int、long、float、double、char、boolean。 3.2 引用数据类型:类、接口、数组。 4. String和StringBuffer有什么区别? String是Java中的一个不可变的字符串类,所有的字符串操作都是创建新的String对象,因此占用大量的内存。而StringBuffer是可变的字符串类,可以动态修改其中的内容,在进行字符串操作时不产生新的String对象,因此可以减少内存的消耗。 5. Java中的异常处理机制是什么? Java的异常处理机制可以帮助程序员处理程序发生的异常情况,包括编译时异常和运行时异常。在Java中,异常由try-catch块捕获,通过throw语句抛出异常。 6. final、finally、finalize有什么区别? final是Java中的一个关键字,可以修饰类、方法和变量。在修饰类时,表示该类不能被继承;在修饰方法时,表示该方法不能被覆盖;在修饰变量时,表示该变量是一个常量,不能被修改。 finally是Java中的一个关键字,可以用在try-catch块中,表示无论try和catch块中的代码是否发生异常,都执行finally块中的代码。 finalize是Java中的一个方法,是Object类中的一个方法,用于垃圾回收时执行的方法,用来释放对象占据的资源。 7. Java中系统输入输出有哪些方法? Java中的System类提供了3种标准I/O流: 7.1 标准输入流:System.in,用于读取用户在命令行中输入的数据。 7.2 标准输出流:System.out,用于将数据输出到命令行中。 7.3 标准错误流:System.err,用于输出错误信息。 8. Java中的多线程是怎么实现的? Java中的多线程机制通过线程对象和run()方法来实现。在Java中,线程是Thread类的对象,每个线程都有自己的run()方法,用于执行线程的任务。通过调用start()方法来启动线程,等到线程调度器分配时间片之后,线程才开始执行。如果要停止执行线程,可以调用stop()方法,但不建议使用该方法,因为可能导致一些不可预料的结果发生。 9. Java中的集合框架有哪些? Java中的集合框架包括Collection和Map两个接口,分别用于存储对象的集合和键值对的映射集合。常用的集合类型包括:List、Set、Map、Queue。 10. Java中的泛型是什么? 泛型是Java中的一个特性,可以使得代码更加灵活和类型安全。通过使用泛型,可以将类型作为参数传递到方法或类中,并在程序运行时根据实际传递的类型进行编译。 以上是Java基础高频面试题(2021最新版),希望对广大读者在Java开发工程师的面试中有所帮助。 ### 回答3: Java是一门广泛应用于各行各业的编程语言,它的应用范围包括大型企业级系统、游戏开发、移动应用程序以及物联网等。Java基础面试题面试Java开发人员时必不可少的环节,下面我简要介绍一些最新的2021Java基础面试题。 1. Java中的四种访修饰符是什么?他们分别表示什么? 答:Java中的四种访修饰符包括:public、protected、private和default(没有显示声明访修饰符,则默认为default)。public表示变量或方法可以在任何地方被调用;protected表示变量或方法限制为同一包内或者其子类中使用;private表示变量或方法只能在当前类中使用;default表示变量或方法在同一包内可见。 2. Java中object类的基本方法有哪些?请解释这些方法的作用。 答:Object类的基本方法包括:equals()、hashCode()、toString()、clone()和finalize()。equals()方法用于判断两个对象是否相等,需要进行重写;hashCode()方法返回一个哈希码值,用于快速查找数据;toString()方法用于返回一个对象的字符串表示形式;clone()方法用于创建一个对象的副本;finalize()方法在垃圾回收之前被调用,用于释放对象占用的资源。 3. 什么是Java中的接口?接口有什么作用? 答:Java中的接口是一个包含方法签名和常量的集合,它可以被类实现。Java中的实现类必须实现接口中定义的所有方法,否则就必须声明自己为抽象类。接口定义了一种规范,使得类可以按照规范进行编写。接口主要用于实现解耦,使开发人员可以更轻松地维护和升级代码。 4. Java中的final关键字有什么作用? 答:final关键字可以用于修饰类、方法和变量。final修饰类表示该类不能被继承;final修饰方法表示该方法不能被子类重写;final修饰变量表示该变量的值不能被修改。final关键字除了保护对象的线程安全和防止错误修改外,还可以提高代码的性能。 5. Java中的static关键字有什么作用? 答:static关键字可以用于修饰类、方法和变量。static修饰类表示该类的变量和方法可以直接通过类名调用,不需要实例化类;static修饰方法表示该方法是属于类的,而不是属于对象的;static修饰变量表示该变量是属于类的,而不是属于对象的。static关键字可以提高程序的性能和代码的复用性。 以上是2021Java基础面试题的简要介绍,当然这些只是一部分,Java基础知识广泛且深刻,希望大家在准备面试时能够多加练习掌握相关知识,从而更好地应对Java面试挑战。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值