当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《静态导入方法的好用例是什么?》经验,为你挑选了6个好方法。

刚收到评论评论我静态导入该方法并不是一个好主意.静态导入是来自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> Ross..:

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

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

(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.*.这样可以更容易地找到导入方法的来源.

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


同意.我偶尔使用静态导入veeery,他们实际上使代码更容易遵循.

2> Rob Hruska..:

静态导入的另一个合理用途是使用JUnit 4.在JUnit方法的早期版本中,类似于assertEquals并且fail自测试类扩展以来继承了这些方法junit.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");
    }
}

JUnit 文档以这种方式使用它.


我们在我们的项目中已经有了这个,并且实际上遇到了使用assert()并且错误地认为它来自静态导入​​Assert包的人的问题.一旦我们发现了这个问题,我们的代码库中的快速扫描在我们的测试中发现了大约30个这样的实例,这意味着在执行测试框架时没有运行30个断言,因为在我们运行测试时没有设置DEBUG标志.
我同意.简化测试用例是意图不太可能被误解的地方.

3> Rob Hruska..:

有效的Java,第二版,在第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会让你进入定义,所以这不是一个问题.

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

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


也许需要缩短"UtilityClassWithFrequentlyUsedMethods".
@SteveKuo肯定少于[InternalFrameTitlePaneMaximizeButtonWindowNotFocusedState](http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b27/com/sun/java/swing/plaf/nimbus/InternalFrameTitlePaneMaximizeButtonWindowNotFocusedState .java#31):P

4> Joel..:

我同意从可读性角度来看它们可能存在问题,应该谨慎使用.但是当使用常见的静态方法时,它们实际上可以提高可读性.例如,在JUnit测试类中,类似assertEquals的方法显而易见.类似的方法来自java.lang.Math.


看到Math.round(d)与round(d)有什么关系呢?
@SteveKuo - 出于同样的原因,数学家在操作公式时使用单字母变量名称:有时候较长的名称会干扰整个语句的可读性.考虑一个涉及多个三角函数的公式.一个容易掌握的数学公式:`sin x cos y + cos x sin y`.在Java中变成:`Math.sin(x)*Math.cos(y)+ Math.cos(x)*Math.sin(y)`.读起来太可怕了.
+1 String.format也可以静态导入

5> jjnguy..:

我经常用它来做Color.

static import java.awt.Color.*;

颜色不太可能与其他东西混淆.



6> softarn..:

我认为静态导入在使用类似Arrays和的utils类时删除多余的类名非常有用Assertions.

不知道为什么,但罗斯跳过了他引用的文档中提到的最后一句话.

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

基本上从这个博客复制: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 numbers = Arrays.asList(1, 2, 3);

// asList method name is enough information
List numbers = asList(1, 2, 3);

java.time包有一些应该使用的情况

// 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");

推荐阅读
夏晶阳--艺术
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有