261

在 Java 中,静态最终变量是常量,并且约定它们应该是大写的。但是,我看到大多数人以小写形式声明记录器,这在PMD中出现了违规行为。

例如:

private static final Logger logger = Logger.getLogger(MyClass.class);

只需在googleSO中搜索“静态最终记录器”,您就会自己看到这一点。

我们应该改用 LOGGER 吗?

4

11 回答 11

334

记录器引用不是常量,而是最终引用,并且不应为大写。一个常量 VALUE 应该是大写的。

private static final Logger logger = Logger.getLogger(MyClass.class);

private static final double MY_CONSTANT = 0.0;
于 2009-09-13T08:40:32.637 回答
257

为了给 crunchdog 的答案增加更多价值,Java 编码风格指南在第 3.3 段字段命名中说明了这一点

用作常量的字段名称应全部大写,用下划线分隔单词。以下被认为是常数:

  1. 所有static final原始类型(请记住,所有接口字段都是固有的static final)。
  2. static final从不跟随“ .”(点)的所有对象引用类型。
  3. static final从不跟随“ [”(左方括号)的所有数组。

例子:

MIN_VALUE, MAX_BUFFER_SIZE, OPTIONS_FILE_NAME

遵循这个约定,loggerstatic final第 2 点中所述的对象引用,但是因为每次使用它后跟“ .”,所以不能将其视为常量,因此应为小写。

于 2012-08-22T09:05:01.683 回答
49

来自有效的 Java,第 2 版,

上一条规则的唯一例外涉及“常量字段”,其名称应由一个或多个由下划线字符分隔的大写单词组成,例如 VALUES 或 NEGATIVE_INFINITY。常量字段是一个静态的 final 字段,其值是不可变的。如果静态最终字段具有原始类型或不可变引用类型(第 15 条),则它是常量字段。例如,枚举常量是常量字段。如果静态最终字段具有可变引用类型,则如果引用的对象是不可变的,它仍然可以是常量字段。

总而言之,常量 == static final,加上如果它是引用(相对于简单类型),则不可变。

查看 slf4j 记录器, http: //www.slf4j.org/api/org/slf4j/Logger.html

它是不可变的。另一方面,JUL 记录器是可变的。log4j 记录器也是可变的。所以正确地说,如果你使用 log4j 或 JUL,它应该是“logger”,如果你使用 slf4j,它应该是 LOGGER。

请注意,上面链接的 slf4j javadocs 页面有一个使用“logger”而不是“LOGGER”的示例。

当然,这些只是惯例而不是规则。如果你碰巧在使用 slf4j 并且你想使用“logger”,因为你已经习惯了其他框架,或者如果它更容易输入,或者为了可读性,请继续。

于 2012-03-01T03:44:44.690 回答
44

我喜欢谷歌的做法(谷歌 Java 风格

每个常量都是静态最终字段,但并非所有静态最终字段都是常量。在选择常量案例之前,请考虑该字段是否真的感觉像一个常量。例如,如果该实例的任何可观察状态都可以改变,那么它几乎肯定不是一个常数。仅仅打算永远不改变对象通常是不够的。

例子:

// Constants
static final int NUMBER = 5;
static final ImmutableList<String> NAMES = ImmutableList.of("Ed", "Ann");
static final Joiner COMMA_JOINER = Joiner.on(',');  // because Joiner is immutable
static final SomeMutableType[] EMPTY_ARRAY = {};
enum SomeEnum { ENUM_CONSTANT }

// Not constants
static String nonFinal = "non-final";
final String nonStatic = "non-static";
static final Set<String> mutableCollection = new HashSet<String>();
static final ImmutableSet<SomeMutableType> mutableElements = ImmutableSet.of(mutable);
static final Logger logger = Logger.getLogger(MyClass.getName());
static final String[] nonEmptyArray = {"these", "can", "change"};
于 2015-06-11T19:07:11.130 回答
10

如果您使用自动化工具来检查您的编码标准并且它违反了上述标准,那么它或标准应该被修复。如果您使用的是外部标准,请修复代码。

在 Sun Java 中,公共静态常量的约定是大写的。显然,记录器不是恒定的,而是表示可变的事物(否则就没有必要在其上调用方法以希望发生某些事情);非常量最终字段没有特定标准。

于 2009-09-13T08:31:49.223 回答
7

如果你用谷歌搜索,你可能会发现在某些情况下,记录器没有被定义为静态最终。对此添加一些快速复制粘贴,这可能会解释它。

我们在所有代码中都使用 LOGGER,这符合我们的命名约定(我们的 CheckStyle 对此很满意)。


我们甚至更进一步,利用 Eclipse 中严格的命名约定。我们使用以下代码模板创建一个新类:

    // private static final Logger LOGGER = Logger.getLogger(${enclosing_type}.class);

记录器被注释掉,因为最初我们不需要它。但是如果我们以后需要它,我们只需取消注释即可。

然后在代码中,我们使用期望此记录器存在的代码模板。使用 try-catch 模板的示例:

    try {
      ${cursor} or some other template
    } catch (Exception t) {
      LOGGER.error("${methodName} ${method parameters}", t);
    }

我们还有一些使用它的模板。

严格的约定使我们能够更高效地使用代码模板并保持一致

于 2009-09-13T09:02:05.020 回答
6

我个人认为它在大写中看起来非常大。此外,由于它是一个与类行为没有直接关系的类,所以我认为使用logger而不是LOGGER. 但是,如果您要严格迂腐,请使用LOGGER.

于 2009-09-13T08:27:29.493 回答
4

不要忘记 PMD 会尊重与

// NOPMD

在里面。这将导致 PMD 从其检查中跳过该行,这将允许您选择您想要的任何样式。

于 2009-09-14T05:14:16.560 回答
3

通常常量是大写的。

但是,如果使用 slf4j 外观,记录器不应该是静态的,而是查找包含类的每个“新”。这避免了特别是 web 容器中的一些讨厌的类加载器问题,而且它允许记录器框架根据调用上下文做一些特殊的事情。

于 2009-09-13T09:21:42.443 回答
2

如果您的编码标准(如果有的话)说它应该是大写的,那么可以。

我看不出任何一种方式有任何严格的理由。我认为这完全取决于您的个人喜好。贵公司的编码标准。

顺便说一句:我更喜欢“记录器”;-)

于 2009-09-13T13:02:35.163 回答
2

我更喜欢'logger',即小写。原因不是它是常量还是不是常量(可变或不可变)。如果我们使用这种推理,如果我们改变日志框架(或者如果框架改变了记录器的可变性),我们就必须重命名变量。

对我来说,其他原因更重要。

  1. 记录器是类中的影子对象,不应该非常突出,因为它没有实现主要逻辑。如果我们使用'LOGGER',它会在代码中吸引太多注意力。

  2. 有时记录器在实例级别声明(即不是静态的),甚至作为依赖项注入。如果我决定更改获取记录器的方式,我不想更改我的代码。代码稳定性。这种(在许多情况下是假设的)变化是我更喜欢小写字母的另一个原因。

于 2019-09-07T22:34:05.180 回答