5

Here is some sample code (assuming Java 8).

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

Is s effectively final inside the loop?

peter.petrov
  • 38,363
  • 16
  • 94
  • 159
  • I don't do it. I ask about "effectively final" assuming that I don't do it. – peter.petrov Feb 11 '16 at 22:33
  • 2
    @cricket_007: If you ***never*** do that, then `s` still is effectively final. – Makoto Feb 11 '16 at 22:33
  • @peter.petrov: It pains me a bit but this duplicate answers your question. In Java 8, this is valid; in Java 7 and older, this is a lot dicier. – Makoto Feb 11 '16 at 22:33
  • 1
    @Reimeus: Does the term "effectively final" even apply to Java 7? – ruakh Feb 11 '16 at 22:34
  • 1
    @cricket_007, Unless I am mistaken, it is basically a Java 8 thing. It has to do with when lambdas can refer to outside variables. – Matthew Feb 11 '16 at 22:35
  • I saw that other question and I don't see how my question is its duplicate. I gave a particular example and just wanted a particular answer. So what is the answer: it is effectively final? – peter.petrov Feb 11 '16 at 22:37
  • The term effectively final has no meaning before Java 8 of course. – peter.petrov Feb 11 '16 at 22:38
  • The answer is in the duplicate question : _"A variable or parameter whose value is never changed after it is initialized is effectively final."_ I don't see why you need a particular answer here, but if you really want to know you can just write a dummy lambda/anonymous class and use `s` to see if it compiles. – Alexis C. Feb 11 '16 at 22:43
  • @AlexisC. I was just arguing about it here http://stackoverflow.com/questions/35350949/multithreaded-server-receives-data-from-just-one-client-java so I wanted to prove I am right :) – peter.petrov Feb 11 '16 at 22:44
  • @AlexisC. What duplicate question are you referring to? – user207421 Feb 11 '16 at 22:45
  • @EJP The one that closed this post, before beeing re-opened (see the edits). – Alexis C. Feb 11 '16 at 22:46
  • @AlexisC. That's not very helpful. For other readers, the question referred to is [here](http://stackoverflow.com/questions/20938095/difference-between-final-and-effectively-final). – user207421 Feb 11 '16 at 22:48

1 Answers1

5

Assuming that s isn't assigned past its declaration, then yes, s is "effectively final", according to the JLS, Section 4.12.4, which defines it, in your case:

Certain variables that are not declared final are instead considered effectively final:

  • A local variable whose declarator has an initializer (§14.4.2) is effectively final if all of the following are true:

    • It is not declared final.

    • It never occurs as the left hand side in an assignment expression (§15.26). (Note that the local variable declarator containing the initializer is not an assignment expression.)

    • It never occurs as the operand of a prefix or postfix increment or decrement operator (§15.14, §15.15).

  • A local variable whose declarator lacks an initializer is effectively final if all of the following are true:

    • It is not declared final.

    • Whenever it occurs as the left hand side in an assignment expression, it is definitely unassigned and not definitely assigned before the assignment; that is, it is definitely unassigned and not definitely assigned after the right hand side of the assignment expression (§16 (Definite Assignment)).

    • It never occurs as the operand of a prefix or postfix increment or decrement operator.

You only assign s at declaration time, and being an object it can't be the operand of an increment or decrement operator, so it is effectively final.

It also states that a variable can be effectively final in another case, if it's not assigned when it's declared, as long it's only assigned once, it's definitely not assigned before the declaration, and it's definitely assigned after the declaration.

Also, at the end of that section, it states:

If a variable is effectively final, adding the final modifier to its declaration will not introduce any compile-time errors. Conversely, a local variable or parameter that is declared final in a valid program becomes effectively final if the final modifier is removed.

You should be able to make it explicitly final without causing a compiler error. If so, it's effectively final.

Community
  • 1
  • 1
rgettman
  • 176,041
  • 30
  • 275
  • 357
  • Hmm. The two sections you quote seem to be at odds regarding cases like `int i; i = 3;`. The former seems to say that `i` is *not* effectively final (since its declarator doesn't have an initializer, and it does occur on the left-hand-side of an assignment statement), whereas the latter seems to say that `i` *is* effectively final (since `final int i; i = 3;` is perfectly valid). Does something else in the spec resolve this apparent discrepancy? – ruakh Feb 11 '16 at 22:52
  • For brevity, I had left the quote of the other way it can become effectively final, in the case of a split declaration/single assignment. I'll include it... – rgettman Feb 11 '16 at 22:53
  • Ah, I see; thanks. I think you were right to prefer brevity. Maybe just leave the second bullet point as "A local variable whose declarator lacks an initializer is effectively final if [...]" -- that is, replace everything after the word "if" with just "[...]"? (Oh, and +1, by the way.) – ruakh Feb 11 '16 at 23:03