由于属性必须是常量表达式错误,Java 代码无法编译
Posted
技术标签:
【中文标题】由于属性必须是常量表达式错误,Java 代码无法编译【英文标题】:Java code won't compile due to attribute must be a constant expression error 【发布时间】: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”。这种错误很多 【参考方案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() 不是可以在编译时计算的——它应该在每次调用时返回不同的值,这意味着在编译时计算它是不可能的。以上是关于由于属性必须是常量表达式错误,Java 代码无法编译的主要内容,如果未能解决你的问题,请参考以下文章