JavaRush /Java 博客 /Random-ZH /Java 开发人员访谈问答分析。第 6 部分

Java 开发人员访谈问答分析。第 6 部分

已在 Random-ZH 群组中发布
你好世界!持续开发对于任何开发人员来说都非常重要。毕竟,如果你停下来,就有可能无人认领并完全飞出市场:IT世界在不断发展和前进,你需要随之前进。但即便如此,我们也不能只关注新技术,以免忘记经典(经典话题)。今天我想继续分析Java开发人员的“经典”主题问题。 Java 开发人员访谈问答分析。 第 6 - 1 部分我注意到我的答案并不是最终权威——这只是我对这些问题的正确答案的看法,你可能不同意其中的一些答案。这很正常,所以请随时在评论中分享您的意见。部分分析的链接位于文章末尾。Java 开发人员访谈问答分析。 第 6 - 2 部分

图书馆和标准

52.什么是休眠?JPA 和 Hibernate 有什么区别?

我认为要回答这个问题,我们首先需要了解JPA是什么。 JPA是一种描述简单 Java 对象的对象关系映射的规范,并提供用于存储、检索和操作此类对象的 API。也就是说,正如我们所记得的,关系数据库(DB)以许多互连表的形式呈现。JPA是一个被广泛接受的标准它描述了对象如何与关系数据库交互。正如您所看到的,JPA是抽象的、无形的东西。这就像想法本身、方法一样。Java 开发人员访谈问答分析。 第 6 - 3 部分同时,Hibernate是一个实现JPA范例的特定库。也就是说,借助该库,您可以通过代表数据库(实体)数据的对象来使用关系数据库。正如他们所说,这个库非常接近JPA的理想,也许这就是它变得流行的原因。正如您所理解的,使用的普及是进一步开发和改进的一个很好的论据。此外,在其频繁使用的背后有一个庞大的社区,该社区已经整理了与该工具相关的所有可能和不可能的问题。这是一本书的示例,详细研究了这项技术的所有黑暗角落。也就是说,Hibernate 已被尽可能多地研究过,并且事实证明是可靠的。事实上,即使是 Spring 端 JPA 的理想实现通常也会在底层使用 Hibernate,这并非没有原因。

53.什么是级联?在Hibernate中是如何使用的?

正如我之前所说,在 Hibernate 中,通信是通过称为实体的数据对象进行的。这些实体代表数据库中的一些特定表,并且您还记得,在 Java 中,类可以包含对其他类的引用。这些关系反映在数据库中。在数据库中,通常,这些是外键(对于 OneToOne、OneToMany、ManyToOne)或中间表(对于 ManyToMany)。您可以在本文中阅读有关实体之间关系的更多信息。当您的实体有到其他相关实体的链接时,注释会放置在这些链接上方以指示连接类型:@OneToOne、@OneToMany、@ManyToOne、@ManyToMane,在其参数中您可以指定属性的值 -级联-此连接的级联类型。JPA有与实体交互的特定方法(持久、保存、合并...)级联类型精确地用于显示在目标实体上使用这些方法时关联数据的行为方式。那么,级联策略(级联的类型)有哪些?JPA 标准暗示使用六种类型的级联:
  • PERSIST - 保存操作将级联发生(对于save()persist()方法)。也就是说,如果我们保存与其他实体关联的实体,它们也会保存在数据库中(如果它们尚不存在)

  • MERGE - 更新操作将级联发生(对于merge()方法)

  • REMOVE - 删除操作级联发生(remove()方法)

  • ALL - 同时包含三个级联操作 - PERSIST - MERGE - REMOVE

JPA有持久实体的概念- 与其在数据库中的数据关联的实体,由当前会话(连接)控制如果更改它,但不将更改保存到数据库中,则其在数据库中的数据仍然会更改。
  • DETACH相关实体将不会由会话管理(detach()方法)。也就是说,当它们发生变化时,它们在数据库中的数据不会自动发生变化——它们从持久化状态转移到分离状态(不由JPA管理的实体)

  • REFRESH - 每次使用数据库中的数据更新实体(刷新() - 更新分离的对象)时,相关实体都会以相同的方式更新。例如,您以某种方式更改了从数据库中获取的数据并希望返回其原始值。在这种情况下,此操作将对您有用。

Java 开发人员访谈问答分析。 第 6 - 4 部分Hibernate 支持所有这些标准级联操作,但也引入了三个自己的操作:
  • REPLICATE - 当我们有多个数据源并且希望数据同步时使用(Hibernate 方法 - 复制)。所有实体都必须有标识符(id),这样它们的生成才不会出现问题(这样同一个实体对于不同的数据库不会有不同的id)

  • SAVE_UPDATE - 级联保存/删除(对于 Hibernate 方法 - saveOrUpdate

  • LOCK是DETACHED的逆操作:它将分离的实体转移回持久化状态,即 实体将再次被当前会话跟踪

如果未选择级联类型,则对实体的任何操作都不会对其关联的其他实体产生任何影响。

54.实体类可以是抽象的吗?

JPA 规范的2.1 实体类中,有一行:“抽象类和具体类都可以是实体。” 所以答案是肯定的,抽象类可以是一个实体,可以用@Entity注解。

55.什么是实体管理者?他负责什么?

首先,我想指出EntityManager是JPA 的关键组件之一,用于实体与数据库的交互。一般来说,它调用实体和数据库之间的交互方法(持久、合并、删除、分离)...但我还要注意的是,这个组件通常并不适用于整个应用程序:大多数情况下它是轻量级的,经常被删除,并使用EntityManagerFactory创建一个新的。如果我们与JDBC进行类比,其中EntityManagerFactory将是DataSource 的类似物,那么EntityManager又将是Connection的类似物。前面我提到了持久性实体,它是由当前连接控制的实体。因此:该实体由 EntityManager精确管理,EntityManager 与当前连接和TransactionManager密切相关,TransactionManager 负责打开/关闭事务。进一步在下图中可以看到实体的生命周期:Java 开发人员访谈问答分析。 第 6 - 5 部分EntityManager在实体处于Managed阶段时对实体进行管理(此时它是持久化的,因为它与EntityManager有连接)。也就是说,它不再是新的并且尚未被删除。我们可以说,当一个实体是新的或被删除时,它也是分离的,因为 它不由 EntityManager 管理。EntityManager 有不同的策略。也就是说,整个应用程序可以有一个单例 EntityManager,也可以每次为每个连接创建一个新的 EntityManager。如果您使用 Spring,那么 EntityManager 的创建/删除是在幕后自动控制的(但这并不意味着您不能自定义它^^)。值得一提的是,一个或多个 EntityManager 形成了持久化上下文持久性上下文是一个环境,其中实体的实例与数据库中的类似实体同步(正如我所说,这只适用于持久性实体)。如果您深入研究JPA(我强烈推荐),您会非常非常频繁地遇到这些概念。

56.什么是Assert类?为什么要使用它?

我在JPA中没有听说过这样的类,所以我假设它指的是库的JUnit类,它用于代码的单元测试。这个库的类Assert是用来检查代码执行的结果(assert是一个声明,表明你在某个地方有某个状态/数据)。例如,您正在测试一种应该创建一只猫的方法。您运行一个方法并得到一些结果:
Cat resultOfTest = createCat();
但您需要确保它已正确创建,对吗?因此,您之前手动创建了一只特定的猫(expectedCat ),其参数与您期望从createCat()方法 获得的猫的参数完全相同。接下来,您使用Assert类来验证结果:
Assert.assertEquals(resultOfTest, expectedCat);
如果猫不同,就会抛出AssertionError异常,这告诉我们预期的结果不收敛。Assert类有许多不同的方法,涵盖了验证预期结果的许多任务。这里是其中的一些:
  • assertTrue(<boolean>) - 作为参数接收的预期值必须为true

  • assertFalse(<boolean>) - 作为参数接收的预期值应该为false

  • assertNotEquals(<object1>, <object2>) - 使用 equals 进行比较时,作为参数接收的对象必须不同 ( false )

  • assertThrows(<ClassNameOfException>.class, <exceptionObject>) - 第二个参数应该是第一个参数指定的类的异常(即,通常,调用一个方法来代替第二个参数,该方法应该抛出所需类型的异常)

细绳

57. Java 中的字符串特征

String是Java中的一个标准类,负责存储和操作字符串值(字符序列),是一个不可变的类(我之前写过不可变的),即 此类对象的数据在创建后就无法更改。我想立即指出,StringBuilderStringBuffer类是两个几乎相同的类,唯一的区别是其中一个类用于多线程环境(StringBuffer)。这些类类似于String,但不同的是,它们是可变的。也就是说,对象一旦创建,就允许修改它们表示的字符串,而无需创建新对象。实际上,这些方法与标准的String方法不同,旨在满足更改字符串的需要(它们被称为构建器并不是没有道理的)。在本文中阅读有关StringStringBufferStringBuilder的更多信息。

58. 创建 String 对象有哪些不同的方法?它是在哪里创建的?

创建字符串的最常见方法是简单地在双括号中指定我们需要的值:
String str = "Hello World!";
您也可以直接通过new执行此操作:
String str = new String("Hello World!");
您可以从字符数组开始创建一个字符串:
char[] charArr = {'H','e','l','l','o',' ', 'W','o','r','l','d','!'};
String str = new String(charArr);
由于toString方法在某个对象上运行:
String str = someObject.toString();
与任何其他方法的结果一样,它返回一个字符串表示形式。例如:
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String str =  reader.readLine();
如您所知,创建字符串的方法可以有非常非常多。当创建String对象时,它将存储在字符串池中,我们将在下面的问题之一中更详细地讨论这一点。

59. Java中如何比较两个字符串以及如何对它们进行排序?

为了在Java中比较值,使用双等号==。如果我们需要比较一些简单的值,比如int,我们会使用它。但这种方法不适用于比较成熟的对象。在这种情况下,它只会比较引用 - 无论它们是否指向同一个对象。也就是说,当比较两个内部字段值完全相同的对象时,通过==进行比较将得到结果false:尽管对象的字段相同,但对象本身占用不同的内存单元。String类的对象尽管看似简单,但仍然是对象。通过==进行比较也不适用于它们(即使存在字符串池)。这里, Object类的标准方法开始发挥作用- equals,必须在类中重写它才能正常工作(否则,默认情况下它使用==进行比较)。它在String类中被重写,因此我们只需获取并使用它:
String firstStr = "Hello World!";
String secondStr = "Hello World!";
boolean isEquals = firstStr.equals(secondStr);
Java 开发人员访谈问答分析。 第 6 - 6 部分我们讨论了匹配比较,现在让我们看看排序比较。毕竟,要对某些东西进行排序,我们需要知道按照什么原则进行排序。为此,您可以使用标准排序集 - TreeSet您可以在本文中阅读有关 Java 中各种集合的更多信息。该列表基于红黑树算法工作,并按照指定的排序原则对集合进行排序。正如我之前所说,您需要了解如何对某种类型的对象进行排序。比较器用于设置排序的比较方法。通常,这些需要为要排序的类实现,但对于String,它们已经实现。因此,我们只需将所需的行添加到TreeSet中,它就会对它们进行排序:
TreeSet<String> sortedSet = new TreeSet<>();
sortedSet.add("B");
sortedSet.add("C");
sortedSet.add("A");
sortedSet.forEach(System.out::println);
控制台输出:
ABC

60.给出一个将字符串转换为字符的算法。编写适当的代码

正如我之前所说,String类的对象有许多不同的有用方法。其中之一是toCharArray。该方法将字符串转换为字符数组:
String str = "Hello world";
char[] charArr = str.toCharArray();
接下来我们有一个可以通过索引调用的字符数组:
char firstChar = charArr[0]; // H

61. 如何将字符串与字节数组相互转换?编写适当的代码

与toCharArray方法类似,String类有一个getBytes方法,它返回字符串的字节数组:
String str = "Hello world";
byte[] byteArr = str.getBytes();
byte firstChar = byteArr[6]; // 119
今天的分析部分已经到了逻辑的终点。感谢您的关注!Java 开发人员访谈问答分析。 第 6 - 7 部分
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION