CodeGym /Java 博客 /随机的 /探索 Java 开发人员职位面试中的问题和答案。第2部分
John Squirrels
第 41 级
San Francisco

探索 Java 开发人员职位面试中的问题和答案。第2部分

已在 随机的 群组中发布
大家好!我们继续为初级、中级和高级 Java 开发人员寻找问题的答案。问题超级有趣。我个人喜欢分析它们,因为它可以帮助我发现理论知识中的差距,有时甚至是最意想不到的地方。 前一部分可以在这篇文章 探索 Java 开发人员职位面试中的问题和答案。 第 2 - 1 部分中找到。但在我们开始之前,我想提醒您:
  1. 我将跳过与本系列文章 重叠的问题,以免不必要地重复信息。我建议阅读这些文章,因为它们涵盖了最常见(流行)的 Java Core 面试问题。
  2. 我可以更详细地描述答案,但我不会,因为这样每个答案都可能拖累整篇文章。在任何工作面试中,没有人会要求您提供如此详细的信息。
如果您愿意,我会留下更深入研究的链接。让我们飞!

11. 命名Object类的所有方法

Object有11个方法:
  1. Class<?> getClass() — 获取当前对象的类;

  2. int hashCode() — 获取当前对象的哈希码;

  3. boolean equals(Object obj) — 将当前对象与另一个对象进行比较;

  4. Object clone() — 创建并返回当前对象的副本;

  5. String toString() — 获取对象的字符串表示形式;

  6. void notify() — 唤醒在此对象监视器上等待的一个线程(线程的选择是随机的);

  7. void notifyAll() — 唤醒在此对象监视器上等待的所有线程;

  8. void wait() — 让当前线程在当前监视器上等待(冻结当前线程),直到notify或notifyAll调用唤醒线程(仅适用于同步块);

  9. void wait(long timeout) — 使当前线程在当前监视器上等待(在当前同步块上),但退出等待状态超时(或者再次,直到notify或notifyAll调用唤醒线程);

  10. void wait(long timeout, int nanos) — 此方法与之前的方法类似,但超时时间更精确;

  11. void Finalize() — 在垃圾收集器删除对象之前(最终)调用此方法。它用于清理获取的资源。

要正确使用hashCodeequalsclonetoStringFinalize方法,必须根据当前任务的具体情况重写它们。

12. 使用资源时,try-with-resources 和 try-catch-finally 有什么区别?

通常,当使用try-catch-finally时,final块用于关闭资源。Java 7 引入了新的try-with-resources语句。它类似于释放资源的 try-catch-finally ,但更紧凑和可读。让我们回想一下try-catch-finally是什么样子的:
String text = "some text......";
BufferedWriter bufferedWriter = null;
try {
   bufferedWriter = new BufferedWriter(new FileWriter("someFileName"));
   bufferedWriter.write(text);
} catch (IOException e) {
   e.printStackTrace();
} finally {
   try {
       bufferedWriter.close();
   } catch (IOException e) {
       e.printStackTrace();
   }
}
现在让我们重写这段代码,但使用try-with-resources
String text = "some text......";
try(BufferedWriter bufferedWriter =new BufferedWriter(new FileWriter("someFileName"))) {
   bufferedWriter.write(text);
} catch (IOException e) {
   e.printStackTrace();
}
现在这有点简单了,你不觉得吗?除了更简单的代码之外,还有其他几点需要注意:
  1. try-with-resources中,括号中声明的资源(将被关闭的资源)必须实现AutoCloseable接口及其唯一的close()方法。

    close 方法在隐式的finally中执行,否则程序如何确定如何关闭资源?

    但是您可能很少会编写自己的资源实现及其关闭方法。

  2. 块按以下顺序执行:

    1. try
    2. 隐式的finally块。
    3. catch块捕获前面步骤中发生的异常。
    4. 显式的finally块。

    通常,列表中较低位置抛出的异常会中断较高位置抛出的异常。

想象一下,您正在使用try-catch-finally并且在try块中遇到异常。然后指定的catch块立即开始执行,其中我们编写了另一个异常(例如,带有更详细地描述错误的消息),并且您希望该方法向上抛出此异常。然后执行finally块,并在其中抛出异常。但这一次有所不同。该方法最终会抛出这两个异常中的哪一个?最后块抛出的异常!但现在我们谈到了有关try-with-resources的另一点。让我们考虑一下try-with-resources在相同情况下的行为方式。当尝试在close()方法中关闭资源时,即在隐式的finally块中,我们在 try 块中遇到异常。catch 块将捕获以下哪些异常?由try块抛出的那个!来自隐式finally块(来自loose()方法)的异常将被忽略。这种对异常的忽略也称为异常抑制。

13.什么是按位运算?

位运算是对位序列的运算。它们包括逻辑运算和按位移位。 逻辑运算符:
  • 按位AND — 比较位值。任何设置为 0 (假) 的位都会将结果中的相应位设置为 0。也就是说,如果两个比较值中的某个位均为 1 (真),则结果位也将为 1。

    表示为AND&

    示例:10111101 & 01100111 = 00100101

  • 按位— 此操作与前一个操作相反。任何设置为 1 的位都会将结果中的相应位设置为 1。因此,如果两个比较值中该位均为 0,则结​​果位也将为 0。

    表示为OR|

    示例:10100101 | 01100011 = 11100111

  • 按位NOT — 该运算符应用于单个值。它翻转(反转)位。即原来为1的位变为0;那些原本为 0 的变成了 1。

    表示为NOT~

    示例:~10100101 = 01011010

  • 按位异— 比较位值。如果两个位均为 1,则结果位为 0。如果两个位均为 0,则结​​果位为 0。换句话说,为了使结果位为 1,只有其中一位必须为 1,并且另一位必须为 0。

    表示为XOR^

    示例:10100101 ^ 01100011 = 11000110

按位移位>><<)将操作数的位按指定方向移位指定的位数。空出的位置用零填充。例如:
  1. 01100011 >> 4 = 00000110
  2. 01100011 << 3 = 00011000
例外情况是当您将负数向右移动时。您还记得,有符号数的第一位表示符号。如果该位为 1,则该数为负数。如果移位负数,则空出的位置不会用零填充,而是用 1 填充,因为必须保留符号位。例如: 10100010 >> 2 = 11101000 也就是说,Java 还有一个附加的无符号右移运算符 (>>>)。该运算符类似于>>,但是当移位时,空出的位置都用0填充,无论操作数是负数还是正数。例如: 10100010 >>> 2 = 00101000在此处 阅读有关按位运算的更多信息。 探索 Java 开发人员职位面试中的问题和答案。 第 2 - 2 部分您可以将HashMap 中的hash()方法作为 Java 中按位移位的示例。此方法用于确定键的特殊内部哈希码: 探索 Java 开发人员职位面试中的问题和答案。 第 2 - 3 部分此方法可以让您均匀分布 HashMap 中的数据,以最大程度地减少冲突次数。

14. Java中有哪些标准的不可变对象?

如果一个对象不允许其原始值改变,则该对象是不可变的。它可能具有返回具有不同值的相同类型的新对象的方法。一些标准的不可变对象包括:
  • 毫无疑问,Java 最著名的不可变类型是 String;
  • 包装标准类型的包装类的实例:Boolean、Character、Byte、Short、Integer、Long、Double、Float;
  • BigInteger 和 BigDecimal 对象,通常用于特别大的数字;
  • 组成堆栈跟踪的 StackTraceElement 对象(例如,异常的堆栈跟踪);
  • File 类的对象——它可以修改文件,但同时对象本身保持不变;
  • UUID,通常用于唯一标识元素;
  • java.time包中类的所有对象;
  • Locale 对象,用于标识地理、政治或文化区域。

15. 不可变对象相对于普通对象有什么优点?

  1. 不可变对象可以安全地在多线程环境中使用。他们这样做是为了让您不必担心由于竞争条件而导致的数据丢失。这与处理普通对象时不同。在这种情况下,在并行环境中使用对象时,您必须思考并想出良好的机制。

  2. 不可变对象非常适合作为映射中的键。如果您使用可变对象作为 HashMap 键,然后该对象的状态发生变化,那么数据结构可能会变得混乱:该对象仍然存在,但如果您使用 containsKey(),您可能找不到它。

  3. 不可变对象非常适合存储在程序运行时永远不应更改的不可变(常量)数据。

  4. 另一个优点是失败原子性。如果不可变对象抛出异常,它不会处于不需要的(损坏的)状态。

  5. 这些类很容易测试。

  6. 您不需要任何额外的机制,例如复制构造函数或对象克隆的实现。

关于面向对象编程的问题

16. 与过程式编程相比,OOP 总体上有哪些优点?

好吧,OOP 的优点:
  1. 使用 OOP 比过程式编程更容易编写复杂的应用程序,因为所有内容都被分解为小模块(彼此交互的对象),因此,编程被简化为对象之间的关系。

  2. 使用 OOP 编写的应用程序更容易修改(当正确遵守设计原则时)。

  3. 由于数据和数据操作都形成一个实体,因此它们不会遍布整个应用程序(过程式编程中经常出现这种情况)。

  4. 封装的原则可以保护用户最关键的数据。

  5. 相同的代码可以与不同的数据重用,因为类允许您创建许多对象,每个对象都有自己的值。

  6. 继承和多态性还允许您重用和扩展现有代码(而不是重复类似的功能)。

  7. 扩展应用程序比使用过程方法更简单。

  8. OOP 方法使得抽象实现细节成为可能。

17.告诉我们OOP有哪些缺点

不幸的是,它们也存在:
  1. OOP 需要大量的理论知识,在编写任何东西之前必须先掌握这些知识。

  2. OOP 思想并不那么容易理解并在实践中应用(你需要内心成为一个小哲学家)。

  3. 由于系统复杂性增加,OOP 会稍微降低程序的性能。

  4. OOP 方法需要更多的内存,因为一切都由类、接口、方法组成,它们比普通变量占用更多的内存。

  5. 初始分析所需的时间比程序方法所需的时间长。

18.什么是静态多态与动态多态?

多态性允许同一类或接口的对象有不同的行为。多态性有两种类型,也称为早期结合和晚期结合。静态多态性,或早期结合:
  • 发生在编译时(程序生命周期的早期);
  • 决定在编译时执行哪个方法;
  • 方法重载是静态多态性的一个例子;
  • 早期绑定包括私有、静态和最终方法;
  • 早期绑定不涉及继承;
  • 静态多态性不涉及特定对象,而是涉及出现在变量名称左侧的类类型信息。
动态多态性,或后期结合:
  • 发生在运行时(程序运行时);
  • 动态多态性决定了方法在运行时将具有哪种具体实现;
  • 方法重写是动态多态性的一个例子;
  • 后期绑定意味着分配一个特定的对象、其类型的引用或其超类;
  • 继承与动态多态性相关。

19. 提供 OOP 中抽象原则的定义

在 OOP 中,抽象是一种隔离对象的一组有意义的特征,同时排除无关紧要的细节的方法。也就是说,当使用 OOP 方法设计程序时,您将重点关注通用模型,而不深入研究其实现的细节。在Java中,抽象是通过接口 来实现的。例如,您有一辆汽车,这将是一个界面。与之进行的各种交互(例如启动发动机、换档)都是函数,我们无需深入研究实现细节即可使用它们。事实上,当您开车时,您不会具体考虑变速箱如何实现其目的,或者钥匙如何启动发动机,或者方向盘如何准确地转动车轮。如果您替换某些功能(例如引擎)的实现,您甚至可能不会注意到它。这对你来说并不重要:你不需要深入研究实现细节。对你来说重要的是行动得到执行。从本质上讲,这抽象了实现细节。至此,今天就到此为止:未完待续!
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION