【问题标题】:Java code won't compile due to attribute must be a constant expression error由于属性必须是常量表达式错误,Java 代码无法编译
【发布时间】:2017-01-02 14:23:15
【问题描述】:

我无法弄清楚为什么以下内容无法编译。 IDE 给我的错误是“注释属性 RequestParam.defaultValue 的值必须是常量表达式”。

我的项目涉及 Spring 和 Maven,具体如下:

private static final String MAX_LONG_AS_STRING = Long.toString(Long.MAX_VALUE);

@RequestMapping(method=RequestMethod.GET)
public List<Spittle> spittles(
        @RequestParam(value="max",
                    defaultValue=MAX_LONG_AS_STRING) long max,
        @RequestParam(value="count", defaultValue="20") int count) {
    return spittleRepository.findSpittles(max, count);
}

我认为错误来自 Long 到 String 的转换,但我不知道如何解决它。我将不胜感激任何帮助,我是注释和 Spring 的新手。

【问题讨论】:

  • @EJP 也许她不明白为什么看起来像常数的东西实际上不是常数?这不是微不足道的。
  • 太棒了,你的例子和我的一样,我也读过“Spring in action”。这种错误很多

标签: java string spring annotations constants


【解决方案1】:

Java 规则规定,当您有一个注解,并且它有一个需要原始类型(例如int)或String 的参数时,该值必须是一个常量表达式时间>。 [这与 Spring 无关。] 粗略地说,常量表达式是编译器可以在编译时计算出其值的表达式。但是,对于什么构成常量表达式有一些规则。这些规则在JLS 15.28 中。只有某些类型的操作可以在常量表达式中使用。方法调用,例如Long.toString(),不是其中之一。所以使用它会使你的表达式 not 成为一个常量表达式,即使它看起来应该是。 (在您看来,它看起来像,因为您知道 Long.toString 做了什么。但是,编译器不会保留所有方法的目录来知道哪些是“常量”方法,其值可以在编译时计算出来。)

但是,链接中的示例显示可以使用 + 运算符,即使其中一个参数不是字符串,因此隐式调用了 toString() 方法。这表明您可以使事情像这样工作:

private static final String MAX_LONG_AS_STRING = "" + Long.MAX_VALUE;

不过我还没试过。

【讨论】:

  • 哦!非常感谢您的帮助,您给我的选项确实有效!您提供的链接和解释确实有助于更多地了解常量表达式。在我进行更多调查之前,我不知道编译时间差异,但不知道它也与方法使用有关。非常感谢您简短而精彩的解释!
  • toString() 是运行时的方法调用。 "" + 5 在编译时创建一个常量字符串(因为它们是不可变的) - 我可能错了
  • @junvar 没有什么可以阻止编译器为Long.toString(Long.MAX_VALUE) 创建常量字符串。有多个 Java 编译器,每个编译器都可以决定是否将其优化为常量字符串。但是,无论编译器如何,Java 关于合法与否的规则都是相同的。合法性规则不依赖于编译器可能会或可能不会进行的可选优化。
  • 为什么静态最终整数 WINDOW_SIZE = 300;也是给我的不是常量表达式,这里没有方法调用?
  • @SumitKandoi 没有。(您可以声明 INSTANCE_ID,但不能在注释中使用它。)您的表达式包含两个方法调用,而常量表达式不能有任何方法调用。此外,randomUUID() 不是可以在编译时计算的——它应该在每次调用时返回不同的值,这意味着在编译时计算它是不可能的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-02-09
  • 1970-01-01
  • 2014-11-13
  • 1970-01-01
  • 2017-02-24
  • 1970-01-01
相关资源
最近更新 更多