面向投资银行资深专业人士的 20 多个核心 Java 面试问题

2025-06-07

面向投资银行资深专业人士的 20 多个核心 Java 面试问题

披露:本帖包含附属链接;如果您通过本文提供的不同链接购买产品或服务,我可能会收到报酬。

有很多Java 开发人员正在尝试在巴克莱、瑞士信贷、花旗银行等投资银行担任 Java 开发职位,但他们中的许多人并不知道在那里会遇到什么样的面试问题。

在本文中,我将分享从投资银行到具有 3 年以上经验的 Java 程序员最常问的一些核心 Java 问题。

披露:本帖包含附属链接;如果您通过本文提供的不同链接购买产品或服务,我可能会收到报酬。

是的,这些问题不适合初学者具有 1 到 2 年 Java经验的专业人士,因为银行通常不会通过公开面试来雇用他们,他们大多以毕业生实习生的身份加入,但他们也可以通过回答问题并理解其背后的答案和概念学到很多东西。

这些问题不一定会被问到,实际上,很可能你不会遇到,但这能让你大致了解面试官会问到哪些问题。准备得越充分,面试效果就越好。

如果您认为这 21 个核心 Java 问题还不够,并且您需要更多内容,请查看这些用于电话面试的额外40 个 Java 问题以及过去 5 年的200 多个 Java 问题。

一旦你完成了这些,你就会更有信心参加任何 Java 面试,无论是电话面试还是面对面面试。

投资银行常见的核心 Java 面试问题

无论如何,不​​要再浪费你的时间了,让我们深入研究一些银行常见的 Java 面试问题,这些问题是我从一些参加过这些银行面试的朋友和同事那里收集的。

问题 1. 不覆盖 hashCode() 方法是否会对性能产生任何影响?答案)\
这是一个好问题,并且对所有人开放,据我所知,较差的哈希码函数将导致HashMap 中频繁发生冲突,最终增加将对象添加到 Hash Map 的时间。

Java 8开始,碰撞不会像在早期版本中那样对性能产生太大影响,因为在达到阈值之后,链表将被二叉树取代,与链表的 O(n) 相比,它在最坏的情况下将为您提供O(logN)性能。

问题 2:String 中的 substring() 如何工作?答案

另一个很好的 Java 面试问题,我认为答案是不够的,但这里是“ Substring 通过获取原始字符串的一部分从源字符串创建一个新对象”

这个问题主要是为了了解开发人员是否熟悉子字符串可能造成的内存泄漏风险。

直到 Java 1.7,子字符串都保存着原始字符数组的引用,这意味着即使子字符串只有 5 个字符长,也可以通过保存强引用来防止 1GB 字符数组被垃圾收集。

这个问题在 Java 1.7 中得到了修复,不再引用原始字符数组,但这一改变也使得创建子字符串的时间开销有点大。之前,它的复杂度在 O(1) 范围内,而从 Java 7 开始,最坏情况下可能会达到 O(n)。

顺便说一句,如果您想了解有关 Java 内存管理的更多信息,我建议您查看Kevin Jones 在 Pluralsight 上撰写的《理解 Java 虚拟机:内存管理》课程。

问题 3:在 Java 中,不可变对象的所有属性都需要是 final 的吗?答案

没有必要,正如链接的答案文章中所述,您可以通过将成员设为非最终但私有的并且除了在构造函数中之外不修改它们来实现相同的功能。

不要为它们提供 setter 方法,如果它是一个可变对象,那么就不要泄漏该成员的任何引用。

请记住,将引用变量设为 final只能确保它不会被重新分配不同的值,但您仍然可以更改该引用变量指向的对象的各个属性。

这是面试官喜欢听应聘者回答的关键点之一。如果你想了解更多关于 Java 中 final 变量的知识,我推荐你参加Udemy 上的“Java 完整大师班”,这是最好的实践课程之一。

问题 4:在多线程环境中可以使用 HashMap 吗?可能存在什么问题?get() 方法什么时候会进入无限循环?答案)\
答:嗯,没什么问题,这取决于如何使用它。例如,如果你只用一个线程初始化一个 HashMap,然后所有线程都只读取它,那么就完全没问题。

其中一个例子是包含配置属性的 Map

真正的问题开始于当至少一个线程正在更新 HashMap 时,即添加、更改或删除任何键值对。

由于 put() 操作可能导致重新调整大小,并可能进一步导致无限循环,因此您应该使用HashtableConcurrentHashMap,后者更好。

问题 5:您能为单例编写一个关键部分代码吗?答案)\
这个核心 Java 问题是另一个常见问题,并期望候选人使用双重检查锁定编写 Java 单例。

记住使用volatile 变量来确保 Singleton线程安全

下面是使用双重检查锁定习惯用法的线程安全单例模式的关键部分代码

public class Singleton {

private static volatile Singleton _instance;

/** * Double checked locking code on Singleton\
    * @return Singelton instance\
*/

public static Singleton getInstance() {

if (_instance == null) {

synchronized (Singleton.class) {

if (_instance == null) {

_instance = new Singleton();

}

}

}

return _instance; }

}
Enter fullscreen mode Exit fullscreen mode

同样,了解像 Singleton、Factory、Decorator 等经典设计模式也是很有好处的。如果您对此感兴趣,那么Java 中的设计模式就是一个很好的集合。

问题 6:编写存储过程或从 Java 访问存储过程时如何处理错误情况?答案

这是Java 面试中比较棘手的问题之一,再次向大家开放,我的朋友不知道答案,所以他不介意告诉我。

我的看法是,如果某些操作失败,存储过程应该返回错误代码,但如果存储过程本身失败,那么捕获SQLException是唯一的选择。

Effective Java》第3版也对处理Java中的错误和异常提出了一些很好的建议,值得一读。

问题 7:Executor.submit() 和 Executer.execute() 方法有什么区别?回答

这个 Java 面试问题来自我的前 50 个 Java 多线程问题答案列表,由于对具有良好并发技能的 Java 开发人员的需求巨大,它变得越来越流行。

这道 Java 面试题的答案是,前者返回一个Future对象,可以用来从工作线程中查找结果)

在异常处理方面,两者有所不同。如果您的任务抛出异常,并且该异常是在执行过程中提交的,则此异常将进入未捕获的异常处理程序(如果您未明确提供异常处理程序,则默认处理程序只会将堆栈跟踪打印到 System.err 中)。

如果您使用方法提交了任务,submit()则任何抛出的异常(无论是否检查异常)都是任务返回状态的一部分。

对于通过提交提交并以异常终止的任务,Future.get() 将重新抛出此异常,并将其包装在 ExecutionException 中。

如果您想了解有关 Future、Callable 和异步计算的更多信息,并将您的 Java 并发技能提升到新的水平,我建议您查看Java Champion Heinz Kabutz 的Bundle 课程中的 Java 并发实践。

这是一门高级课程,基于Brian Goetz所著的经典著作《Java 并发实践》 ,该书被誉为 Java 开发者的圣经。这门课程绝对值得你投入时间和金钱。由于并发是一个棘手且棘手的主题,因此将本书和课程结合起来是学习它的最佳方式。

问题 8:工厂模式和抽象工厂模式有什么区别?答案)\
答:抽象工厂模式提供了更高层次的抽象。设想一下,不同的工厂模式各自扩展自一个抽象工厂,并负责根据工厂类型创建不同层次的对象。例如,抽象工厂模式由汽车工厂模式、用户工厂模式、角色工厂模式等扩展而成。每个工厂模式都负责创建该类型的对象。

如果您想了解有关抽象工厂设计模式的更多信息,那么我建议您查看Java 课程中的设计模式,它提供了一个很好的真实示例来更好地理解模式。

这是工厂和抽象工厂模式的 UML 图:

如果您需要更多选择,那么您还可以查看我的前 5 个 Java 设计模式课程列表。

问题 9:什么是 Singleton?是使整个方法同步更好,还是仅同步关键部分更好?答案)\
Java 中的 Singleton 是整个 Java 应用程序中只有一个实例的类,例如,java.lang.Runtime就是一个 Singleton 类。

在 Java 4 之前创建 Singleton 比较棘手,但是一旦 Java 5 引入了Enum ,创建就变得非常容易。

您可以参阅我的文章《如何在 Java 中创建线程安全的单例》,了解有关使用枚举和双重检查锁定编写单例的更多详细信息,这也是本 Java 面试题的目的。

问题 10:你能在 Java 4 和 Java 5 中编写迭代 HashMap 的代码吗?答案)\
这道题比较棘手,但他成功地用 while 和 for 循环写出来了。实际上,在 Java 中迭代任何 Map 的方法有四种,其中一种是使用keySet()迭代某个键,然后使用get()方法获取值,这种方法开销有点大。

第二种方法涉及使用entrySet()并通过使用for each 循环或 while 与 Iterator.hasNext() 方法对其进行迭代。

这是一种更好的方法,因为在迭代期间键和值对象都可供您使用,并且您不需要调用get()方法来检索值,如果一个存储桶中有一个巨大的链表,这可以提供 O(n) 性能。

您可以进一步参阅我的帖子《在 Java 中迭代 Map 的 4 种方法》以获取详细解释和代码示例。

问题 11:何时覆盖 hashCode() 和 equals()?回答)\
必要时,特别是当您想根据业务逻辑而不是对象相等性进行相等性检查时,例如,如果两个员工对象具有相同的,则它们是相等的emp_id,尽管事实上它们是两个不同的对象,由代码的不同部分创建。

此外,如果您想将它们用作HashMap中的键,则必须重写这两种方法。

现在,作为 Java 中 equals-hashcode 契约的一部分,当您覆盖 equals 时,您也必须覆盖 hashcode,否则,您的对象将无法破坏类的不变性,例如 Set、Map,它们依赖equals()方法才能正常运行。

您还可以查看我的帖子“有关 Java 中 equals 的 5 个技巧”,以了解处理这两种方法时可能出现的细微问题。

问题 12:如果不覆盖 hashCode() 方法,会出现什么问题?答案)\
如果不覆盖 equals 方法,则 equals 和 hashcode 之间的契约将不起作用,根据该契约,两个通过 equals() 相等的对象必须具有相同的 hashcode

在这种情况下,另一个对象可能会返回不同的 hashCode 并将存储在该位置,这会破坏HashMap 类的不变性,因为它们不应该允许重复的键。

使用 put() 方法添加对象时,它会遍历该 bucket 位置中存在的所有 Map.Entry 对象,如果 Map 中已经包含该键,则更新前一个映射的值。如果未覆盖哈希码,则此方法无效。

如果你想了解更多关于 Java 集合(如 Map 和 Set)中 equals() 和 hashCode() 的作用,我建议你学习Richard Warburton 在 Pluralsight 上讲授的Java 基础:集合课程。

问题 13:同步 getInstance() 方法的临界区还是同步整个 getInstance() 方法,哪个更好?答案)\
答案仅仅是临界区,因为如果我们锁定整个方法,那么每次有人调用此方法时,都必须等待,即使我们没有创建对象。

换句话说,仅当您创建对象时才需要同步,而且只发生一次。

一旦对象创建,就不需要任何同步。事实上,这种代码在性能方面非常糟糕,因为同步方法会降低性能 10 到 20 倍。

以下是单例设计模式的 UML 图:

顺便说一句,有几种方法可以在 Java 中创建线程安全的单例,包括Enum,您也可以将其作为该问题或任何后续问题的一部分提及。

如果您想了解更多信息,还可以查看学习 Java 中的创建设计模式--- Udemy 的 #FREE 课程。

问题 14:在 HashMap 上的 get() 操作期间,equals() 和 hashCode() 方法在哪里出现?答案)\
这个核心 Java 面试问题是前面 Java 问题的后续,应聘者应该知道,一旦你提到 hashCode,人们最有可能问,它们是如何在 HashMap 中使用的。

当你提供一个键对象时,首先会调用它的 hashcode 方法来计算 bucket 的位置。由于 bucket 可能包含多个条目(以链表形式),因此会使用 equals() 方法对每个 Map.Entry 对象进行求值,以判断它们是否包含实际的键对象。

我强烈建议您阅读我的帖子《HashMap 在 Java 中的工作原理》,这是另一个关于采访的故事,以了解有关该主题的更多信息。

问题 15:如何避免 Java 中的死锁?答案)\
如果您知道,当两个线程尝试访问彼此持有的两个资源时会发生死锁,但要发生这种情况,需要满足以下四个条件:

  1. 互斥\ 至少一个进程必须处于非共享模式。
  2. 保持并等待\ 必须有一个进程持有一个资源并等待另一个资源。
  3. 禁止抢占\资源不能被抢占。
  4. 循环等待\ 必须存在一组进程

您可以通过打破循环等待条件来避免死锁。为了做到这一点,您可以在代码中做出安排,强制执行锁的获取和释放顺序。

如果以一致的顺序获取锁并以相反的顺序释放锁,就不会出现一个线程持有另一个线程获取的锁,反之亦然的情况。

您可以进一步查看我的帖子“如何在 Java 中避免死锁”以获取代码示例和更详细的解释。

我还推荐Udemy 上 Michael Pogrebinsky 撰写的《Java 多线程、并发和性能优化》 ,以便 Java 开发人员更好地理解并发模式。

问题 16:使用 new() 和文字创建 String 之间有什么区别?答案)\
当我们在 Java 中使用 new() 运算符创建一个 String 对象时,它是在堆中创建的,而不是添加到字符串池中,而使用文字创建的 String是在堆的 PermGen 区域中的字符串池本身中创建的。

String str = new String("Test")

没有将对象str放入字符串池中,需要调用String.intern()方法显式地将它们放入字符串池中。

仅当您创建一个 String 对象作为 String 文字时,例如String s = "Test"Java 才会自动将其放入 String 池中。

顺便说一下,这里有一个问题,因为我们传递的参数是“Test”,它是一个字符串文字,它还会在字符串池中创建另一个对象“Test” 。

这一点一直以来都被忽视了,直到Javarevisited博客的博主指出了这一点。想了解更多关于字符串字面量和字符串对象的区别,请参阅这篇文章。

这里有一张很好的图片,可以很好地展示出这种差异:

问题 17:什么是不可变对象?你能写出不可变类吗?答案)\
不可变类是 Java 类,其对象一旦创建就无法修改。对不可变对象的任何修改都会产生新的对象,例如,Java 中的 String 是不可变的

在 Java 中,大多数不可变类也是final 的,以防止子类覆盖方法,因为这可能会损害不可变性。

您可以通过使成员非最终但私有并且除了在构造函数中之外不修改它们来实现相同的功能。

除了显而易见的之外,您还需要确保不要暴露不可变对象的内部结构,特别是如果它包含可变成员。

类似地,当您从客户端接受可变成员的值时java.util.Date,请使用clone() 方法为自己保留一个单独的副本,以防止恶意客户端在设置可变引用后修改它的风险。

在返回可变成员的值时,也需要采取同样的预防措施,返回另一个单独的副本给客户端,切勿返回 Immutable 类持有的原始引用。您也可以阅读我的博文《如何在 Java 中创建 Immutable 类》,其中提供了分步指南和代码示例。

问题 18:不使用任何分析工具,如何最简单地找出某个方法的执行时间?答案)\
在方法调用之前和方法返回之后读取系统时间。计算时间差,即可得出方法的执行时间。

请记住,如果执行时间太短,它可能会显示执行时间为零毫秒。请在一个足够大的方法上尝试一下,也就是说,这个方法正在执行大量的处理。

问题 19:要将任何对象用作 HashMap 中的键,需要实现哪两种方法?答案)\
为了将任何对象用作 HashMap 或 Hashtable 中的键,它必须在 Java 中实现equalshashcode方法。

您还可以阅读HashMap 在 Java 中的工作原理,了解有关如何使用 equals 和 hashcode 方法在 HashMap 中放置和获取对象的详细说明。

问题 20:如何防止客户端直接实例化你的具体类?例如,你有一个 Cache 接口和两个实现类 MemoryCache 和 DiskCache,你如何确保客户端不会使用 new() 关键字创建这两个类的对象? \
我把这个问题留给你练习和思考,然后再给出答案。我相信你能找到正确的方法,因为这是确保类控制权掌握在你手中的重要决策之一,从维护的角度来看,这非常有益。

进一步学习

  1. 完整的 Java 大师班
  2. Java 基础知识:Java 语言
  3. 为缺乏耐心的用户提供核心 Java SE 9
  4. 200+ Java 面试题
  5. 在 Java 编程面试中脱颖而出

结束语

太棒了!你终于读完了这篇文章……祝你 Java 编程面试顺利!这当然不会轻松,但只要你遵循这些问题,你离目标就更近了一步。

如果您想收到我的新帖子通知,请考虑在 Medium 上关注我(javinpaul ),并且不要忘记在Twitter上关注我!

文章来源:https://dev.to/javinpaul/20-core-java-interview-questions-for-experienced-professionals-from-investment-banks-53b7
PREV
由 CSS 自定义属性支持的视差
NEXT
.NET Core 依赖注入:你应该知道的一切 TLDR;我从构建 Coravel 中学到的东西:第三部分 什么是依赖注入?为什么我们应该将依赖项作为参数传递?什么是依赖注入(重温) 快速了解测试 快速了解模块化 避免类继承 在 .NET Core 中使用依赖注入 真实示例 真实测试 你应该了解的关于使用 .NET Core 依赖注入的知识 结论 导航你的软件开发职业通讯