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

问题

刚刚得到评论评论,我的方法的静态导入不是一个好主意。静态导入是来自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 热门回答(116 赞)

这是Sun发布该功能时的指南(重点是原创):

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

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

我想特别提到两个部分:

  • 仅在你试图"滥用继承"时才使用静态导入。在这种情况下,你是否想要让BusinessObject扩展some.package.DA?如果是这样,静态导入可能是一种更清晰的处理方式。如果你从来没有想过扩展some.package.DA,那么这可能是静态导入的一个不好用。输入时不要仅用于保存几个字符。
  • 导入个人会员。比如导入静态some.package.DA.save而不是DA。*。这样可以更容易地找到导入方法的来源。

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


#2 热门回答(54 赞)

静态导入的另一个合理用途是使用JUnit 4.在早期版本的JUnit中,类似assertEqualsfail的方法从测试类extendedjunit.framework.TestCase继承。

// old way
import junit.framework.TestCase;

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

在JUnit 4中,测试类不再需要扩展TestCase,而是可以使用注释。然后,你可以从org.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");
    }
}

JUnitdocuments用这种方式。


#3 热门回答(20 赞)

Effective Java, Second Edition,在项目19的末尾,你可以使用静态导入,如果你发现自己使用实用程序类中的常量。我认为这个原则适用于常量和方法的静态导入。

import static com.example.UtilityClassWithFrequentlyUsedMethods.myMethod;

public class MyClass {
    public void doSomething() {
        int foo= UtilityClassWithFrequentlyUsedMethods.myMethod();
        // can be written less verbosely as
        int bar = myMethod();
    }
}

这有利有弊。它使代码更具可读性,代价是丢失一些关于定义方法的直接信息。但是,一个好的IDE会让你进入定义,所以这不是什么大问题。

你仍然应该谨慎使用它,并且只有你发现自己使用导入文件中的东西很多次。

**编辑:**更新为更具体的方法,因为这是这个问题所指的。无论输入什么(常数或方法),该原则都适用。