JavaRush /Java 博客 /Random-ZH /喝咖啡休息#134。编写 Java 代码时要避免什么。Java中如何使用final、finally和finaliz...

喝咖啡休息#134。编写 Java 代码时要避免什么。Java中如何使用final、finally和finalize

已在 Random-ZH 群组中发布

编写 Java 代码时应避免什么

来源:Medium 我们提请您注意一篇文章,其中列出了开发人员在编写 Java 代码时常犯的错误。 喝咖啡休息#134。 编写 Java 代码时要避免什么。 Java中如何使用final、finally和finalize - 1

使用 Enum.values

这被认为是一个错误让我感到惊讶,因为我经常使用Enum.values。这里的问题是Enum.values()按照规范应该是一个不可变的列表。为此,每次调用时都必须返回带有枚举值的新数组实例。
public enum Fruits {
    APPLE, PEAR, ORANGE, BANANA;

    public static void main(String[] args) {
        System.out.println(Fruits.values());
        System.out.println(Fruits.values());
    }
}
// output
// [Lcom.test.Fruits;@7ad041f3
// [Lcom.test.Fruits;@251a69d7
这里内存中有两个独立的对象,因此看起来似乎没什么大不了的。但是,如果您在处理请求时使用Fruit.values()并且负载很高,那么这可能会导致内存问题。您可以通过引入私有静态最终变量 VALUES 进行缓存 来轻松解决此问题。

将可选参数作为方法参数传递

考虑以下代码:
LocalDateTime getCurrentTime(Optional<ZoneId> zoneId) {
    return zoneId.stream()
        .map(LocalDateTime::now)
        .findFirst()
        .orElse(LocalDateTime.now(ZoneId.systemDefault()));
}
我们传递可选参数zoneId,并根据它的存在来决定是给出系统时区的时间还是使用指定的时区。但是,这不是使用Optional 的正确方法。我们应该避免使用它们作为参数,而应使用方法重载。
LocalDateTime getCurrentTime(ZoneId zoneId) {
  return LocalDateTime.now(zoneId);
}

LocalDateTime getCurrentTime() {
  return getCurrentTime(ZoneId.systemDefault());
}
您在上面看到的代码更容易阅读和调试。

使用字符串生成器

Java 中的字符串是不可变的。这意味着一旦创建它们就不再可编辑。JVM 维护一个字符串池,在创建新字符串池之前,会调用String.intern()方法,该方法会从字符串池中返回与该值对应的实例(如果存在)。假设我们想要通过将元素连接到其中来创建一个长字符串。
String longString = new StringBuilder()
  .append("start")
  .append("middle")
  .append("middle")
  .append("middle")
  .append("end")
  .toString();
最近我们被告知这是一个非常糟糕的主意,因为旧版本的 Java 执行了以下操作:
  • 在第 1 行,字符串“start”被插入字符串池并由longString指向
  • 第 2 行将字符串“startmiddle”添加到池中,并用longString指向它
  • 在第 3 行我们有“startmiddlemiddle”
  • 第 4 行 - “startmiddlemiddlemiddle”
  • 最后在第 5 行,我们将“startmiddlemiddlemiddleend”添加到池中并将longString指向它
所有这些行都保留在池中并且从未使用过,导致大量 RAM 被浪费。为了避免这种情况,我们可以使用 StringBuilder。
String longString = new StringBuilder()
  .append("start")
  .append("middle")
  .append("middle")
  .append("middle")
  .append("end")
  .toString();
当调用toString方法 时,StringBuilder 仅创建一个字符串,从而摆脱最初添加到池中的所有中间字符串。但是,在 Java 5 之后,这是由编译器自动完成的,因此最好使用“+”进行字符串连接。

在不需要时使用原始包装器

考虑以下两个片段:
int sum = 0;
for (int i = 0; i < 1000 * 1000; i++) {
  sum += i;
}
System.out.println(sum);
Integer sum = 0;
for (int i = 0; i < 1000 * 1000; i++) {
  sum += i;
}
System.out.println(sum);
在我的计算机上,第一个示例的运行速度比第二个示例快六倍。唯一的区别是我们使用 Integer 包装类。Integer 的工作方式是,在第 3 行,运行时必须将 sum 变量转换为原始整数(自动拆箱),加法完成后,将结果包装到新的 Integer 类中。(自动包装)。这意味着我们正在创建 100 万个 Integer 类并执行 200 万个打包操作,这解释了速度急剧下降的原因。仅当需要将包装类存储在集合中时才应使用包装类。然而,Java 的未来版本将支持原始类型的集合,这将使包装器过时。

Java中如何使用final、finally和finalize

来源:Newsshare 在本文中,您将了解 Finalize 关键字的使用地点、时间和原因,以及它是否值得在 Java 中使用。您还将了解 Final、finally 和 Finalize 之间的区别。

哪里使用了finally块?

Java 中的finally 块用于容纳代码的重要部分,例如清理代码、关闭文件或关闭连接。无论是否引发异常或是否处理该异常,finally 块都会执行。无论是否发生异常,finally 都包含所有重要的语句。

Java 中如何终结变量?

Java 变量的初始化有 3 种方法:
  • 您可以在声明最终变量时对其进行初始化。这种方法是最常见的。
  • 空的最终变量在实例初始化块或构造函数中初始化。
  • 空的最终静态变量在静态块内初始化。

我们可以在Java中手动调用finalize方法吗?

Finalize()方法不是必需的,也不建议在对象超出范围时调用。因为事先并不知道finalize()方法何时(或者是否)会被执行。一般来说,除非有特殊需要,否则 Finalize 并不是最好的方法。从 Java 9 开始,它已被弃用。

Finalize方法什么时候被调用?

Finalize()方法在垃圾回收之前被调用以执行清理。

Final、finally 和 Finalize 和有什么不一样?

Final、finally 和 Finalize 之间的主要区别在于,final 是访问修饰符,finally 是异常处理中的块,而 Finalize 是对象类的方法。

是否可以重写final方法?

不可以,声明为 Final 的方法不能被覆盖或隐藏。

我们可以使用 try 而不使用 catch 吗?

是的,通过使用Final块,可以有一个没有catch块的try块。我们知道,即使try块中发生了System以外的异常,finally块也总是会被执行。

什么是最终方法?

Final 方法不能被子类覆盖或隐藏。它们用于防止子类修改对类的功能或一致性可能至关重要的方法的意外行为。

构造函数可以是最终的吗?

构造函数永远不能被声明为最终的。你的编译器总是会抛出一个错误,比如“不允许使用final修饰符”。Final 当应用于方法时意味着该方法不能在子类中被重写。构造函数不是常规方法。

finally 关键字有什么用?

finally 关键字用于在 try 块后面创建一个代码块。无论是否发生异常,finally 块都会被执行。使用finally 块允许您运行您想要执行的任何展开类型语句,而不管受保护的代码中发生了什么。

最后有什么用?

Java 中的finally 块是用于执行部分代码(例如关闭连接等)的块。Java中的finally块无论异常是否被处理都会被执行。因此,它包含了无论是否发生异常都需要打印的所有必要语句。

为什么 Finalize 方法受到保护?

为什么Finalize()方法访问修饰符受到保护?为什么不能公开呢?它不是公开的,因为它不应该被 JVM 以外的任何人调用。但是,它必须受到保护,以便可以被需要为其定义行为的子类覆盖。

Java中是否总是调用finalize方法?

当对象即将被垃圾回收时,将调用 Finalize 方法。这可能在它符合垃圾回收条件后的任何时间发生。请注意,该对象完全有可能永远不会被垃圾回收(因此永远不会调用 Finalize)。

投掷和投掷有什么区别?

throw 关键字用于有意抛出异常。throws 关键字用于声明一个或多个异常,并以逗号分隔。使用 throw 时,仅抛出一个异常。

try catch 和finally 关键字有什么区别?

这是两个不同的概念:只有当 try 块中发生异常时,才会执行 catch 块。无论是否抛出异常,finally 块始终在 try(-catch) 块之后执行。

在Java中我们可以不用try直接使用finally吗?

finally 块必须与 try 块关联,如果没有 try 块,则不能使用finally。您必须将那些必须始终执行的语句放置在此块中。

我们可以继承final方法吗?

最终方法是继承的吗?是的,final 方法是继承的,但你不能覆盖它。

哪个方法不能被覆盖?

我们不能重写静态方法,因为方法重写是基于运行时的动态链接,而静态方法是在编译时使用静态链接绑定的。因此,重写静态方法是不可能的。

如果最终方法被重写会发生什么?

父类中声明的final方法不能被子类覆盖。如果我们尝试重写最后一个方法,编译器将在编译时抛出异常。

Final关键字和finalize方法的作用相同吗?

除了名称相似外,它们的功能没有相似之处。Final关键字可以与Java中的类、方法或变量一起使用。在 Java 中,final 类不可扩展,final 方法不能被覆盖,final 变量也不能被修改。

Java中的super关键字是什么?

Java中的super关键字是一个引用变量,用于引用父类的直接对象。每当实例化子类时,都会并行创建父类的实例,该实例由引用变量 super 引用。super关键字可以用来直接调用父类的方法。

static 和final 关键字有什么区别?

static 和final 关键字之间的主要区别在于,static 关键字用于定义类的成员,该成员可以独立于该类的任何对象使用。Final关键字用于声明常量变量、不可重写的方法和不可继承的类。
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION