【问题标题】:import static vs. static final导入静态与静态最终
【发布时间】:2013-01-29 13:47:39
【问题描述】:

过去我经常在 Java 类中使用“import static”构造。最近我意识到,而不是

import static my.pack.A.MY_CONSTANT;

你可以使用

import my.pack.A;

public class B {
    private static final MY_CONSTANT = A.MY_CONSTANT;
}

这种方法最明显的优点是:

  1. 您可以在 Eclipse 中使用重构轻松地从代码中删除所有长常量表达式,例如 A.B.C.CONSTANT.ANOTHER_ONE.TOO_LONG,而不会弄乱静态导入(在 Eclipse 中掌握起来并不那么快)
  2. 您可以为任何表达式指定任何名称,这在当前上下文中可能更有意义。

例如:

private static final PAYMENT_TYPE = PaymentType.CASH;
...
calculateSomething(amount, PAYMENT_TYPE);

而不是

import static my.pack.PaymentType.CASH
...
calculateSomething(amount, CASH);

如果默认 PaymentType 值更改为 CREDIT_CARD,这也更容易重构。

我的问题是:与静态导入相比,这种方法有什么缺点吗?或者它可以在任何地方使用吗?

我现在唯一关心的是生成的编译后的 .class 文件,这可能与所描述的两种方法不同。所以理论上性能和内存使用可能会受到影响。

【问题讨论】:

  • 您是否考虑过使用 Enums 代替?他们似乎更适合这种情况。
  • 不确定,枚举如何解决我将一些现有常量导入类文件的问题。实际上,枚举的值可以通过任何一种方式导入,类似于常量。
  • 能不能同时编译两个版本,反编译对比一下区别?
  • 太抽象了。 PaymentType 看起来像接口常量反模式。
  • 嗯,枚举不需要静态导入,它们是隐式静态的。

标签: java performance memory import constants


【解决方案1】:

我认为唯一的缺点是你有更多的代码,你将一个常量分配给另一个常量。除此之外应该没有区别。性能和内存无关紧要,您可能会有更多引用返回到相同的常量池条目。即使它创建了单独的常量池条目,也需要很多条目才能有所作为。

在无法重命名原始条目的情况下,能够为常量命名可能是一件好事。

【讨论】:

    【解决方案2】:

    这主要是口味问题,但官方docs 建议谨慎使用static 版本,尤其是带有通配符的版本。静态导入的主要缺点是它通过添加所有静态成员来污染您的命名空间。在您上面的示例中,它应该与您认为对您的代码更具可读性的内容有关。除非你真的想要package 的所有static 成员,否则不要做“导入包。*”的冲动。

    它不应该影响你的编译代码——它只是提供对同一常量的简写访问。

    【讨论】:

    • 当我确定导入的常量在导入它的类的上下文中具有某些意义时,我倾向于进行静态导入。 “import static my.pack.PaymentType.*”在 IDE 中很容易自动转换为“import static my.pack.PaymentType.CASH”。我什至有这个动作绑定到保存文件。这也是“static final”的一个优点——因为它在客户端类的上下文中具有更有意义的名称。