静态导入方法的良好用例是什么?

2022-08-31 07:27:26

刚刚收到一条评论,说我对该方法的静态导入不是一个好主意。静态导入是来自 DA 类的方法,该类主要具有静态方法。因此,在业务逻辑的中间,我有一个显然属于当前类的da活动:

import static some.package.DA.*;
class BusinessObject {
  void someMethod() {
    ....
    save(this);
  }
} 

审稿人并不热衷于我改变代码,我没有,但我确实同意他的观点。给出的不静态导入的一个原因是,它令人困惑的是定义方法的位置,它不在当前类中,也不在任何超类中,因此它也需要一些时间来识别其定义(基于Web的审查系统没有像IDE这样的可点击链接:-)我真的不认为这很重要,静态进口仍然是相当新的,很快我们都会习惯于找到它们。

但另一个原因,我同意,是非限定方法调用似乎属于当前对象,不应该跳转上下文。但是,如果它确实属于,那么扩展这个超级类是有意义的。

那么,静态导入方法在什么时候有意义?你什么时候做过?您是否/是否喜欢不合格呼叫的外观?

编辑:流行的观点似乎是,如果没有人将它们混淆为当前类的方法,则静态导入方法。例如,来自java.lang.Math和java.awt.Color的方法。但是,如果abs和getAlpha不是模棱两可的,我不明白为什么readEmployee是。与许多编程选择一样,我认为这也是个人偏好的问题。


答案 1

这是来自Sun发布该功能时的指南(强调原文):

那么什么时候应该使用静态导入呢?非常谨慎!仅当您试图声明常量的本地副本或滥用继承(常量接口反模式)时,才使用它。...如果过度使用静态导入功能,它可能会使程序不可读且不可维护,从而用导入的所有静态成员污染其命名空间。你的代码的读者(包括你,在你写完代码几个月后)将不知道静态成员来自哪个类。从类中导入所有静态成员可能对可读性特别有害。如果只需要一个或两个成员,请单独导入它们。

(https://docs.oracle.com/javase/8/docs/technotes/guides/language/static-import.html)

我想特别指出两个部分:

  • 当您试图“滥用继承”时才使用静态导入。在这种情况下,你会忍不住要有业务对象吗?如果是这样,静态导入可能是处理此问题的更干净方法。如果您从未梦想过扩展,那么这可能是静态导入的不良使用。不要在键入时仅将其用于保存几个字符。extend some.package.DAsome.package.DA
  • 导入单个成员。而不是说 .这将使查找此导入方法的来源变得更加容易。import static some.package.DA.saveDA.*

就个人而言,我很少使用这种语言功能,而且几乎总是只使用常量或枚举,从不使用方法。对我来说,这种权衡几乎从来都不值得。


答案 2

静态导入的另一个合理用途是 JUnit 4。在早期版本的JUnit方法中,由于测试类扩展,因此被继承了。assertEqualsfailjunit.framework.TestCase

// old way
import junit.framework.TestCase;

public class MyTestClass extends TestCase {
    public void myMethodTest() {
        assertEquals("foo", "bar");
    }
}

在 JUnit 4 中,测试类不再需要扩展,而可以使用注释。然后,您可以从 中静态导入断言方法:TestCaseorg.junit.Assert

// new way
import static org.junit.Assert.assertEquals;

public class MyTestClass {
    @Test public void myMethodTest() {
        assertEquals("foo", "bar");
        // instead of
        Assert.assertEquals("foo", "bar");
    }
}

JUnit 以这种方式使用它进行文档。


推荐