是否应在UPPER-CASE中声明"静态最终记录器"?

dog*_*ane 232 java logging static final naming-conventions

在Java中,静态最终变量是常量,惯例是它们应该是大写的.但是,我已经看到大多数人声称记录器是小写的,这在PMD中是违规的.

例如:

private static final Logger logger = Logger.getLogger(MyClass.class);
Run Code Online (Sandbox Code Playgroud)

只需搜索谷歌SO搜索"静态最终记录器",你就会看到这个.

我们应该使用LOGGER吗?

cru*_*dog 288

记录器引用不是常量,而是最终引用,不应该是大写的.常量VALUE应为大写.

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

private static final double MY_CONSTANT = 0.0;
Run Code Online (Sandbox Code Playgroud)

  • 静态最终引用是常量,如果它们是不可变的.通过这个逻辑,你永远不会有常量字符串,因为任何静态最终字符串都是引用. (41认同)
  • 但是java.lang.String**是不可变的,无论如何都是一种特殊的类(参见String.intern(),有关Sring池的文档等) (28认同)
  • 如果有人仍然关心这个问题,请在https://github.com/checkstyle/checkstyle/issues/23分享想法,以区分需求大写和不在哪里. (4认同)
  • immutable意味着对象的状态在构造之后不能改变.看我下面的帖子.记录器不一定是可变的. (3认同)
  • @Jeach我不认为不变性与状态如何变化有关,仅与状态有关。而且,什么是用户?外部用户正在运行该程序?您是否可以区分用户按下按钮修改的状态和计时器以某个随机间隔触发的状态?(我不这么认为)。 (2认同)
  • 我们在工作中也有过类似的辩论。这个线程有助于澄清这个问题,但我还使用以下示例为支持大写的人提供了一个例外。有谁知道为什么java有`serialVersionUID`而不是`SERIAL_VERSION_UID`?`private static final long serialVersionUID = 201208271956L;` (2认同)

cbl*_*ard 220

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

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

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

例子:

MIN_VALUE, MAX_BUFFER_SIZE, OPTIONS_FILE_NAME
Run Code Online (Sandbox Code Playgroud)

遵循此约定,loggerstatic final第2点中所述的对象引用,但因为每次使用它时都会跟着" .",所以它不能被视为常量,因此应该是小写.

  • 我没有得到第2点.什么是从未跟随点的对象类型的示例.所有对象类型都继承自`Object`,您可以在它们上调用诸如`.equals`之类的方法. (14认同)
  • 我见过的最佳定义.链接的doc似乎已移到这里更新http://www.cs.bilgi.edu.tr/pages/standards_project/java_CodingStyle.pdf#page7 (11认同)
  • 你是对的.当查看一些Java常量,如Boolean.TRUE,Boolean.FALSE,TimeUnit.MINUTES,String.CASE_INSENSITIVE_ORDER或Collections.EMPTY_LIST时,它们之后也可能跟着`.`. (5认同)
  • @RomanIvanov我在这里再次找到它:http://www.scribd.com/doc/15884743/Java-Coding-Style-by-Achut-Reddy由Achut Reddy撰写,最后更新于2000年5月30日 (5认同)
  • 这不是重点。关键是你不应该对存储的对象引用做任何事情。这意味着使用 `Logger` 对象(例如 `log.info(...)`)违反了规则 2,因为 `log` 在该调用中后跟一个点。由于您不能像在 C++ 中那样将方法标记为 `const`,因此假定所有方法都会改变对象,因此不是常量。 (2认同)

Jef*_*man 43

从有效的java,第2版.,

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

总之,常量==静态最终,加上它是一个引用(与简单类型相比),不变性.

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

这是不可改变的.另一方面,JUL记录器是可变的.log4j记录器也是可变的.所以要正确,如果你使用log4j或JUL,它应该是"logger",如果你使用的是slf4j,它应该是LOGGER.

请注意,上面链接的slf4j javadocs页面有一个示例,它们使用"logger"而不是"LOGGER".

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

  • `Logger`**接口究竟是如何***不可变*?只有`final class`(如`String`或`Integer`)才能保证不变性.即使你找不到SLF4J`Logger`的任何可变实现,也没有人能阻止你自己写一个. (5认同)
  • 我不知道检查风格的规则.如果它只是坚持任何静态决赛应该是大写的,那么是的,这是错误的. (3认同)
  • 基于这种推理,checkstyle的简单定义是不合适的吗? (2认同)

mat*_*scb 35

我喜欢谷歌对它的看法(Google Java Style)

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

例子:

// 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"};
Run Code Online (Sandbox Code Playgroud)

  • 我认为第一句话总结了这一点:"每个常量都是静态的最终字段,但并非所有静态最终字段都是常量." 它很容易使用机械思维,并且每个静态的最终字段都是大写的(我一直这样做直到现在),但这是错过了语言的微妙之处. (6认同)

Pet*_*ham 10

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

Sun Java中的约定是公共静态常量的大写.显然,记录器不是常量,而是代表一个可变的东西(否则就没有必要在它上面调用方法,希望会发生一些事情); 对于非常数最终字段没有特定标准.

  • 你为什么说记录器不是恒定的?它似乎确实不变.日志记录生成是调用其方法的副作用,但不会更改其可观察状态.我错过了什么? (10认同)
  • 记录器不是常量,因为它是对象的引用.常量是无法更改的值.对象引用是final(因此对它的引用不能更改,例如与其他东西交换或设置为null)但对象本身可以. (5认同)
  • 如果它是一个StringBuilder而不是一个记录器,那么它可能更明显是非常量的.即使对于记录器,Logger.setLevel()等方法也会显着地改变接收器.通常大写是针对那些语言视为常量并将内联的常量. (3认同)

KLE*_*KLE 7

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

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


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

    // private static final Logger LOGGER = Logger.getLogger(${enclosing_type}.class);
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

严格的惯例使我们的工作效率和连贯的代码模板.

  • 捕捉Throwable是不好的做法,除非你记录并重新抛出它.记住错误:OutOfMemeoryError等.事件异常在多线程应用程序中被您自己捕获和处理是不安全的. (5认同)
  • Eclipse语法是:Logger.getLogger($ {enclosing_type} .class); (2认同)

Joã*_*lva 6

我个人认为它在大写中看起来非常大.而且,因为它是一个与类行为没有直接关系的类,所以我没有看到使用logger而不是使用的主要问题LOGGER.但如果你要严格迂腐,那就用吧LOGGER.