实践还是理论?更重要的是什么呢?很多人会说,当然,练习更重要。就像,尽可能努力地练习,你会很高兴。我敢于不同意这一点。 在面试过程中,没有人会知道你的练习水平如何。我们将根据理论详细地询问您。只有这样,当你经历了各轮面试并进入项目后,你才会运用你的实际技能。你可能会反对:有时他们会给你一个测试任务,但仍然需要练习。我不争论,它们有时会被给出,但事实是有时会发生,但理论访谈总是会发生。你感觉有什么不同吗?所以,你脚下必须有扎实的理论基础,我们今天要继续加强这一点。也就是说,我们将继续分析采访中经常被问到的问题。
并且不要忘记硬币的另一面:隔离级别越高,处理事务所需的时间就越长(如果多个事务并行执行)。如果您想深入研究这个主题,这里有一篇很棒的文章可以帮助您入门。
71. 如果我们不重写 Enum 的 toString() 方法会发生什么?
假设我们有以下枚举:public enum Role {
STUDENT,
TEACHER,
DIRECTOR,
SECURITY_GUARD;
}
让我们通过调用学生的 toString()在控制台 中显示学生:
System.out.println(Role.STUDENT.toString());
控制台中的结果:
学生
也就是说,默认情况下,枚举的toString()是常量本身的名称。
72. 是否可以在 Enum 中指定构造函数?
是的,当然。内部枚举变量的值是通过构造函数设置的。作为示例,让我们向前面的枚举添加两个字段——ageFrom和ageTo——以指示每个角色的年龄范围:public enum Role {
STUDENT(5,18),
TEACHER(20,60),
DIRECTOR(40,70),
SECURITY_GUARD(18,50);
int ageFrom;
int ageTo;
Role(int ageFrom, int ageTo) {
this.ageFrom = ageFrom;
this.ageTo = ageTo;
}
}
73. == 和 equals() 有什么区别?
这是最常见的 Java 开发人员面试问题之一。让我们从这样一个事实开始:当我们比较简单值(int、char、double ...)时,我们使用==来进行,因为变量包含特定值,我们可以比较它们。原始变量不是成熟的对象 - 它们不是从Object继承,也没有equals()方法。当我们谈论比较引用对象的变量时,==只会比较引用的值 - 无论它们是否引用同一个对象。即使一个对象与另一个对象相同,通过==进行比较也会给出负结果 ( false ),因为这是一个不同的对象。如您所知,equals()方法用于比较引用变量。这是Object类的标准方法之一,需要对对象进行完整的比较。但值得立即澄清的是:为了使该方法正确工作,需要通过准确编写如何比较此类的对象来重新定义它。除非您重写该方法,否则默认情况下它将通过==比较对象。在IntelliJ IDEA中,您可以自动覆盖它(使用 IDEA 工具) -> alt + insert,在出现的窗口中,选择equals() 和 hashCode() -> 选择哪些类字段应该参与 -> 瞧,自动实现方法已完成。下面是一个自动生成的equals方法的示例,该方法对于具有两个字段(intage和String name)的简单Cat类来说是这样的:@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || this.getClass() != o.getClass()) return false;
final Cat cat = (Cat) o;
return this.age == cat.age &&
Objects.equals(this.name, cat.name);
}
如果我们讨论枚举的 == 和 equals 之间的区别,其实并没有太多区别。毕竟,枚举存储常量,即使使用==比较相似的值,我们也会收到true,因为引用始终是相同的对象。好吧,当使用equals 时,我们也会正确地计算出功能,特别是如果你进入enum的equals方法的主体,你会看到在Enum类中该方法的实现如下:里面 - 很好的旧比较参考!总结一下:对于enum,通过==和equals进行比较是正确的。
74. Enum 中的ordinal()方法有什么作用?
当对枚举元素调用int ordinal ()方法时,我们将得到该值在一般枚举系列中从零开始的序数。让我们在前面讨论的枚举中的一个元素上使用此方法- Role:System.out.println(Role.DIRECTOR.ordinal());
相应地,控制台将显示:
2
75. 在Java中是否可以将Enum与TreeSet或TreeMap一起使用?
在TreeSet和TreeMap中使用枚举类型是可以接受的。我们可以写:TreeSet<Role> treeSet = new TreeSet<>();
treeSet.add(Role.SECURITY_GUARD);
treeSet.add(Role.DIRECTOR);
treeSet.add(Role.TEACHER);
treeSet.add(Role.STUDENT);
treeSet.forEach(System.out::println);
并且控制台会显示:
学生 教师 主任 SECURITY_GUARD
我们收到的输出不是按字母顺序排列的。要点是,如果我们使用enum元素作为TreeSet值或作为TreeMap 的键,则元素将按其自然顺序(它们在enum中指定的顺序)排序。了解这些功能有助于我们编写更好的代码。
76. Enum 中的ordinal() 和compareTo() 方法有何关系?
如前所述,ordinal()返回通用枚举列表中值的序数。另外,在对上一个问题的分析中,您看到枚举的元素(例如,在TreeSet (排序集)中)采用它们在enum中声明的顺序。正如我们所知,TreeSet和TreeMap通过调用Comparable接口的compareTo()方法对元素进行排序。由此我们可以假设Enum类实现了Comparable接口,并在compareTo()方法中实现了它,其中ordinal()用于设置排序顺序。进入Enum类后,我们看到了这一点的确认:以及方法本身的主体:这里没有调用ordinal()方法。相反,使用序数变量- 枚举中元素的序号。ordinal()方法本身只不过是序数变量的 getter 。77. 编写一个 EnumM 示例
在上面讨论的问题中,我已经给出了枚举的示例,并且我不认为重复代码有什么意义(例如,关于枚举中的构造函数的问题 72)。78. 是否可以在 switch case 中使用 Enum?
这是可能的,也是必要的!回顾我的实践,我注意到使用enum最常见的地方之一是像switch这样的逻辑结构。在这种情况下,您可以提供case 的所有可能变体,并且在编写所有枚举值的逻辑之后-甚至可能不需要使用默认运算符!毕竟,如果您使用String或数值(例如int类型),您可能会收到意外的值,而使用enum则是不可能的。对于前面讨论的示例, 开关会是什么样子:public void doSomething(Role role) {
switch (role) {
case STUDENT:
// некая логика для STUDENT
break;
case TEACHER:
// некая логика для TEACHER
break;
case DIRECTOR:
// некая логика для DIRECTOR
break;
case SECURITY_GUARD:
// некая логика для SECURITY_GUARD
break;
}
}
79.如何获取Enum实例中所有可用的值?
如果您需要获取枚举的所有实例,可以使用value()方法,该方法以自然顺序(按照它们在enum中指定的顺序)返回特定枚举的所有可用值的数组。例子:Role[] roles = Role.values();
for (Role role : roles) {
System.out.println(role);
}
控制台将显示以下输出:
学生 教师 主任 SECURITY_GUARD
流媒体接口
80.Java中的Stream是什么?
Java Stream是一种相对较新的与数据流交互的方式,这反过来又允许您更方便、更紧凑地处理大数据,以及在一定数量的线程之间并行化数据处理,这可以提高使用时的性能功能。简而言之,这个主题无法更深入地讨论,因此我将在此处留下一篇文章的链接,以帮助您深入了解该主题。81. 交易的主要属性是什么?
主题叫Stream API,但问题是关于事务的。嗯...首先,我们来了解一下什么是交易。 事务是一组顺序数据库操作,表示处理数据的逻辑单元。事务可以完全成功地完成,保持数据完整性并独立于并行运行的其他事务,或者根本无法完成,在这种情况下它没有任何影响。所以,事务有四个主要属性,简称ACID。我们来看看这个缩写的每个字母代表什么: A - Atomicity - 原子性- 这个属性保证没有交易会被部分记录在系统中。要么执行其所有子操作,要么不执行任何子操作(全部或全无)。 C - Consistency(一致性)——一致性是确保每个成功的事务只记录有效结果的属性。也就是说,这是一种保证,在交易成功的情况下,系统对特定数据施加的所有规则和限制都将得到满足,否则交易将无法完成,系统中的数据将返回到之前的状态。状态。 I - Isolation - 隔离是一个属性,表示在事务执行期间,并行事务不应影响其结果。此属性是资源密集型的,因此通常通过允许一定程度的绝缘来解决某些绝缘问题来部分实现。我们将在下一个问题中更详细地讨论这一点。D - 持久性 -该属性确保如果用户从系统收到交易已完成的确认,他可以确定他所做的更改不会由于某些故障而被取消。也就是说,如果您已经收到交易成功完成的确认信息,则可以确定某种操作系统故障不会对您的数据产生任何影响。82. 事务隔离级别是什么?
正如我之前所说,提供 ACID 隔离是一个资源密集型过程。因此,该性质得到部分满足。隔离有不同的级别,级别越高,对生产力的影响就越大。在讨论事务隔离级别之前,我们需要先看看事务隔离不足的各种问题:-
幻读——同一个事务中重复调用同一个样本(同一个查询)时,收到的数据不同,这是由于另一个事务插入数据造成的;
-
非重复读取——当在同一个事务中重复调用相同的样本(相同的查询)时,接收到的数据不同,这是由于另一个事务对数据的更改(更新)和删除而发生的;
-
脏读- 读取事务添加或更改的数据的过程,该数据随后未被确认(回滚),即 读取无效数据;
-
丢失更新——当不同事务同时更改相同数据时,除了最后一个更改之外的所有更改都会丢失(让人想起多线程环境中的“竞争条件”问题)。
隔离级别 | 幻读 | 不重复阅读 | 脏读 | 丢失更新 |
---|---|---|---|---|
可串行化 | + | + | + | + |
可重复读取 | - | + | + | + |
已提交读 | - | - | + | + |
未提交的阅读 | - | - | - | + |
没有任何 | - | - | - | - |
83.Statement和PreparedStatement有什么区别?
而这里向JDBC技术的特性过渡并不是很顺利。所以,首先,让我们弄清楚Statement实际上是什么。这是一个用于生成 SQL 查询的对象。JDBC使用三种类型:Statement、PreparedStatement和CallableStatement。 今天我们不看CallableStatement :我们来谈谈Statement和PreparedStatement之间的区别。-
语句用于执行简单的 SQL 查询,无需传入、动态插入的参数。使用PrepareStatement能够动态插入输入参数。
-
要在PreparedStatement中设置参数,请求中的输入参数会被写成问号,这样就可以使用各种设置器插入值,例如setDouble()、setFloat()、setInt()、setTime() ... 。因此,您不会在查询中插入错误类型的数据。
-
PreparedStatement是“预编译的”并使用缓存,因此它的执行速度可能比从Statement对象查询稍快。因此,经常执行的 SQL 查询被编写为PreparedStatement对象以提高性能。
-
Statement很容易受到 SQL 注入的攻击,而PreparedStatement可以防止它们。在本文中阅读有关消除 SQL 注入和 Java 安全性中其他最佳实践的更多信息。
GO TO FULL VERSION