2016-02-11 93 views
5

这里是一些示例代码(假设Java 8)。这个“s”有效吗?

while (true){ 
    Socket s = serverSocket.accept(); 
    // some code here ... we don't assign anything to s again here ... 
} 

s有效最终在循环内吗?

+0

我不这样做。假设我不这么做,我会问“有效的最终”。 –

+2

@ cricket_007:如果你从来没有这样做过,那么's'仍然是有效的。 – Makoto

+0

@ peter.petrov:它让我感到有些痛苦,但是这个重复可以回答你的问题。在Java 8中,这是有效的;在Java 7和更高版本中,这是非常复杂的。 – Makoto

回答

5

假设s没有分配过去的声明,那么,s是“有效的最后”,根据JLS, Section 4.12.4,它定义它,你的情况:未申报

某些变量最终被代替考虑有效最终

  • 的局部变量,其说明符具有一个初始化(§14.4.2)是有效最终如果以下全部属实:

    • 未声明final

    • 它永远不会出现在赋值表达式(§15.26)中的左侧。 (请注意,包含初始化局部变量声明符是赋值表达式。)

    • 它永远不会发生作为前缀或后缀增量或减量操作者(§15.14,§15.15)的操作数。

  • 一个局部变量,其声明符缺少初始化实际上最终如果以下所有条件都为真:

    • 它不声明为final。

    • 每当它出现在赋值表达式中的左手边时,它肯定是未分配的,并且在赋值之前没有明确赋值;也就是说,它肯定是未赋值的,并且在赋值表达式(§16(定义赋值))的右侧之后没有明确赋值。

    • 它永远不会发生作为前缀或后缀增量或减量运算符的操作数。

你只在声明时分配s,并作为一个对象时,它不能是递增或递减的运算数,所以它是有效的决赛。

它还声明变量在另一种情况下可以是有效的最终结果,如果它在声明时没有被赋值,只要它只被赋值一次,它肯定不会在声明前被赋值,并且在声明后明确赋值。

此外,在该节结束时,它指出:

如果一个变量是有效final,加上final修饰符其声明将不会引入任何编译时错误。相反,如果删除了final修饰符,则在有效程序中声明为final的局部变量或参数将有效。

您应该能够明确地将其设置为final而不会导致编译器错误。如果是这样,那实际上是最终的。

+0

嗯。你引用的两个部分似乎对于像'int i'这样的情况不一致。我= 3;'。前者似乎认为'i' *不是*有效的最终结果(因为它的声明者没有一个初始化器,它确实发生在赋值语句的左侧),而后者似乎是说'i' * *实际上是最终的(因为'final int i; i = 3;'完全有效)。规范中的其他内容是否可以解决这种明显的差异? – ruakh

+0

为简洁起见,我已经将其他方式的引用留下来,在分割声明/单个赋值的情况下,它可以成为有效的最终结果。我会包括它...... – rgettman

+0

啊,我明白了;谢谢。我认为你更喜欢简洁是对的。也许只是把第二个要点留作“一个局部变量,其声明符缺少一个初始化符,如果[...]”实际上是最终的,也就是说,用“[...]”替换单词“if”后面的所有内容? (顺便说一句,哦,还有+1。) – ruakh