代码之家  ›  专栏  ›  技术社区  ›  Miserable Variable

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

  •  114
  • Miserable Variable  · 技术社区  · 16 年前

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

    评论员不希望我修改代码,我也没有,但我确实同意他的观点。不进行静态导入的一个原因是它混淆了方法的定义位置,它不在当前类中,也不在任何超类中,因此需要一些时间来确定它的定义(基于web的审阅系统没有像IDE:-)这样的可点击链接),我真的认为这不重要,静态导入仍然很新,很快我们都会习惯于定位它们。

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

    那么,什么时候 静态导入方法有意义吗?你什么时候做的?你喜欢不合格电话的样子吗?

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

    16 回复  |  直到 3 年前
        1
  •  162
  •   ktulinho jeremfg    7 年前

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

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

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

    我想特别指出两个部分:

    • 使用静态导入 只有 当你被诱惑“滥用遗产”时。在这种情况下,您是否会尝试使用BusinessObject extend some.package.DA some.package.DA ,那么这可能是静态导入的不当使用。输入时不要仅仅为了保存几个字符而使用它。
    • 导入单个成员。 import static some.package.DA.save 而不是 DA.* . 这将更容易找到这个导入的方法的来源。

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

        2
  •  67
  •   Rob Hruska MegalomanINA    16 年前

    静态导入的另一个合理用途是JUnit4。在JUnit方法的早期版本中,例如 assertEquals fail junit.framework.TestCase .

    // old way
    import junit.framework.TestCase;
    
    public class MyTestClass extends TestCase {
        public void myMethodTest() {
            assertEquals("foo", "bar");
        }
    }
    

    TestCase 并且可以使用注释。然后可以从中静态导入assert方法 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");
        }
    }
    

    documents 这样使用它。

        3
  •  30
  •   Lii bob    4 年前

    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可以让您进入定义,所以这不是什么大问题。

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

        4
  •  20
  •   softarn    4 年前

    Arrays Assertions .

    不知道为什么,但罗斯省略了最后一句话,其中提到了这一点 documentation he is referencing .

    如果使用得当,静态导入可以通过删除重复类名的样板文件使程序更具可读性。

    https://medium.com/alphadev-thoughts/static-imports-are-great-but-underused-e805ba9b279f

    例如:

    这是我认为大家都同意的最明显的情况

    Assertions.assertThat(1).isEqualTo(2);
    
    // Use static import instead
    assertThat(1).isEqualTo(2);
    

    Utils类和枚举

    在许多情况下,使用utils类时可以删除类名,从而使代码更易于阅读

    List<Integer> numbers = Arrays.asList(1, 2, 3);
    
    // asList method name is enough information
    List<Integer> numbers = asList(1, 2, 3);
    

    // Get next Friday from now, quite annoying to read
    LocalDate.now().with(TemporalAdjusters.next(DayOfWeek.FRIDAY));
    
    // More concise and easier to read
    LocalDate.now().with(next(FRIDAY));
    

    不使用时的示例

    // Ok this is an Optional
    Optional.of("hello world");
    
    // I have no idea what this is 
    of("hello world");
    
        5
  •  17
  •   Rob Hruska MegalomanINA    14 年前

    assertEquals 很明显他们来自哪里。类似地,对于来自 java.lang.Math .

        6
  •  11
  •   jjnguy Julien Chastang    16 年前

    static import java.awt.Color.*;
    

    颜色不太可能与其他颜色混淆。

        7
  •  5
  •   Tunaki    9 年前

    我建议使用 静态导入 “大量使用实用程序类中的常量” 类别

    认为

    import static android.opengl.GLES20.*;
    

    允许您移植原始C代码并编写可读的内容,例如:

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texture);
    glUniform1i(samplerUniform, 0);
    glBindBuffer(GL_ARRAY_BUFFER, vtxBuffer);
    glVertexAttribPointer(vtxAttrib, 3, GL_FLOAT, false, 0, 0);
    

    GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture);
    GLES20.glUniform1i(samplerUniform, 0);
    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vtxBuffer);
    GLES20.glVertexAttribPointer(vtxAttrib, 3, GLES20.GL_FLOAT, false, 0, 0);
    
        8
  •  3
  •   Fracdroid    10 年前

    在将大量数学代码从C/C++移植到java时,我使用“import static java.lang.Math.*”。数学方法将1映射为1,使得在没有类名限定的情况下更容易区分移植的代码。

        9
  •  2
  •   Bombe    16 年前

    由于您刚才提到的问题,静态导入是Java唯一的新特性,我从未使用过,也不打算使用。

        10
  •  2
  •   Yeikel    6 年前

    我发现这在使用实用程序类时非常方便。

    if(CollectionUtils.isNotEmpty(col))

    我可以:

    import static org.apache.commons.collections.CollectionUtils.isNotEmpty;
    if(isNotEmpty(col))
    

    当我在代码中多次使用此实用程序时,IMO会提高代码的可读性。

        11
  •  2
  •   Yash    5 年前

    谈论单元测试:大多数人使用静态导入来实现 嘲笑 when() verify() .

    import static org.mockito.Mockito.verify;
    import static org.mockito.Mockito.when;
    

    当然,当使用您应该使用的唯一断言时 assertThat()

    import static org.hamcrest.Matchers.*;
    
        12
  •  1
  •   kdgregory    16 年前

    它们有助于减少冗长,特别是在调用大量导入方法的情况下,并且本地方法和导入方法之间的区别很明显。

    一个示例:涉及对java.lang.Math的多个引用的代码

    另一个: An XML builder class 其中,在每个引用前加上类名将隐藏正在构建的结构

        13
  •  1
  •   Matthias Wuttke    11 年前

    我认为静态导入对于gettext风格的NLS来说是很好的。

    import static mypackage.TranslatorUtil._;
    
    //...
    System.out.println(_("Hello world."));
    

    这既可以将字符串标记为必须提取的字符串,也可以提供一种简单、干净的方法来用翻译替换字符串。

        14
  •  1
  •   eldjon    10 年前

    Util 提供一些静态方法和属性的类。通过建立代码标准,可以避免在提供静态导入时产生的歧义。根据我在一家公司的经验,这种方法是可以接受的,并且使代码更干净、更容易理解。我最好插入 _ 前面的字符静态方法和静态属性 . 显然,这种方法违反了Java的命名标准,但它提供了代码的清晰性。例如,如果我们有一个AngleUtils类:

    public class AngleUtils {
    
        public static final float _ZERO = 0.0f;
        public static final float _PI   = 3.14f;
    
        public static float _angleDiff(float angle1, float angle2){
    
        }
    
        public static float _addAngle(float target, float dest){
    
        }
    }
    

    import static AngleUtils.*;
    
    public class TestClass{
    
        public void testAngles(){
    
            float initialAngle = _ZERO;
            float angle1, angle2;
            _addAngle(angle1, angle2);
        }
    }
    

    有人可以马上知道哪个方法或属性来自静态导入,它隐藏了它所属类的信息。我不建议对作为模块组成部分的类使用静态导入,并提供静态和非静态方法,因为在这种情况下,了解哪个类提供特定的静态功能很重要。

        15
  •  -1
  •   Meneer Venus    10 年前

    您需要在以下情况下使用它们:

    • 您希望使用 switch
    • 您希望使您的代码难以理解
        16
  •  -5
  •   Javamann    16 年前

    我尽可能地使用它们。如果我忘记了,我有IntelliJ设置来提醒我。我认为它看起来比完全限定的包名干净得多。

    推荐文章