静态导入方法的好用例是什么?
刚刚得到审查意见,我静态导入的方法是不是一个好主意。 静态导入是来自DA类的一种方法,它大部分是静态方法。 所以在商业逻辑中间,我有一个显然属于当前阶层的活动:
import static some.package.DA.*; class BusinessObject { void someMethod() { .... save(this); } }
审查人员并不热衷于我改变了代码,我没有,但是我也同意他的意见。 给定不静态导入的一个原因是定义方法的地方很混乱,它不在当前类中,也不在任何超类中,所以它也有一段时间来确定它的定义(基于web的审阅系统没有可点击的像IDE这样的链接:-)我真的不觉得这很重要,静态导入仍然是很新的,很快我们都会习惯于定位它们。
但另一个我同意的理由是,一个无条件的方法调用似乎属于当前的对象,不应该跳转上下文。 但是,如果真的属于这个,那么扩展这个超类就是有意义的。
那么,什么时候对静态导入方法有意义呢? 你什么时候做的? 你喜欢不合格的电话的样子吗?
编辑:stream行的意见似乎是静态导入方法,如果没有人会混淆他们作为当前类的方法。 例如来自java.lang.Math和java.awt.Color的方法。 但是,如果ABS和getAlpha不含糊不清,我不明白为什么readEmployee是。 就像很多节目select一样,我认为这也是个人喜好的事情。
谢谢你们的回复,我正在closures这个问题。
这是从Sun的指南,当他们发布的function(重点在原来的):
那么什么时候应该使用静态导入? 非常谨慎! 只有当你想要声明本地副本的常量或滥用inheritance(Constant Interface Antipattern)时才使用它。 …如果您过度使用静态导入function,可能会使您的程序无法读取并且无法维护,从而导致您导入的所有静态成员污染其名称空间。 你的代码的读者(包括你,在你写了几个月后)不会知道静态成员来自哪个类。 从类中导入所有静态成员对可读性尤其有害; 如果您只需要一个或两个成员,请单独导入它们。
( http://java.sun.com/j2se/1.5.0/docs/guide/language/static-import.html )
我想具体说出两个部分:
- 只有当您试图“滥用inheritance” 时才使用静态导入。 在这种情况下,你是否会试图让BusinessObject
extend some.package.DA
? 如果是这样,静态导入可能是一个更清洁的方式来处理这个。 如果你永远不会梦想扩展some.package.DA
,那么这可能是一个不好的使用静态导入。 input时不要用它来保存几个字符。 - 导入个人会员 说
import static some.package.DA.save
而不是DA.*
。 这将使得更容易find这个导入的方法来自哪里。
就我个人而言,我很less使用这种语言function,几乎总是只使用常量或枚举,而不使用方法。 对于我来说,权衡几乎是不值得的。
静态导入的另一个合理用途是使用JUnit 4.在早期版本的JUnit方法(如assertEquals
和fail
中,testing类扩展了junit.framework.TestCase
。
// old way import junit.framework.TestCase; public class MyTestClass extends TestCase { public void myMethodTest() { assertEquals("foo", "bar"); } }
在JUnit 4中,testing类不再需要扩展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 文档 。
有效的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会让你去定义,所以这不是一个问题。
你应该仍然使用这个节制,只有当你发现自己多次使用导入的文件的东西。
编辑:更新为更具体的方法,因为这就是这个问题所指的。 无论导入什么(常量或方法),该原则都适用。
我用它很多颜色。
static import java.awt.Color.*;
颜色与别的东西混淆是不太可能的。
我同意他们从可读性的angular度来看可能是有问题的,应该谨慎使用。 但是,当使用通用的静态方法时,他们实际上可以提高可读性。 例如,在JUnittesting类中,像assertEquals
这样的方法显然来自哪里。 类似的,来自java.lang.Math
方法。
由于刚刚提到的问题,静态导入是我从来没有使用过,也不打算使用的Java的唯一“新”function。
我认为静态导入对于gettext风格的NLS来说是整洁的。
import static mypackage.TranslatorUtil._; //... System.out.println(_("Hello world."));
这既将string标记为必须提取的string,又提供了一种简单且干净的方法来将stringreplace为其翻译。
IMO静态导入是一个不错的function。 严重依赖静态导入使得代码不可读,难以理解静态方法或属性属于哪一类。 不过,以我的经验来看,它成为一个可用的function,特别是在devise提供一些静态方法和属性的Util
类时。 每当提供静态导入时产生的歧义可以通过build立代码标准来规避。 根据我在公司内部的经验,这种方法是可以接受的,并使代码更加清晰易懂。 最好我插入_
前面的静态方法和静态属性(从某种程度上采用C)字符。 显然这种方法违反了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); } }
有人可以告诉哪个方法或属性来自静态导入,并隐藏它所属的类的信息。 我不build议使用静态导入作为模块的组成部分的类,并提供静态和非静态方法,因为在这种情况下知道哪个类提供某些静态function很重要。
将C / C ++中的math代码移植到java时,我使用“import static java.lang.Math。*”。 math方法映射1到1,并且使得移植的代码更容易,而不需要类名限定。
您需要在以下情况下使用它们:
- 你希望使用带有枚举值的
switch
语句 - 你希望使你的代码难以理解
我build议在使用OpenGL和Java时使用静态导入 ,这是一个用例,属于“大量使用来自工具类的常量”类
考虑一下
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);
它们有助于减less措辞,特别是在调用大量import方法的情况下,本地和import方法之间的区别是明确的。
一个例子:包含多个java.lang.Math引用的代码
另一个: 一个XML构build器类 ,将类名添加到每个引用将隐藏正在构build的结构
我尽可能地使用它们。 我有IntelliJ安装程序提醒我,如果我忘了。 我认为它看起来比完全合格的软件包名称更清洁。