Final (Java): Difference between revisions

Content deleted Content added
Final variables: Replaced wrong and inaccurate statements about final variables with correct and precise statements and good code example
Line 95:
Since the obj variable goes out of scope with each iteration of the loop, it is actually redeclared each iteration, allowing the same token (i.e. <code>obj</code>) to be used to represent multiple variables.<ref>{{cite web|url=http://www.cs.cmu.edu/~pattis/15-1XX/15-200/lectures/morejava/lecture.html|title=More Java|last=Pattis|first=Richard E.|work=Advanced Programming/Practicum 15–200|publisher=School of Computer Science [[Carnegie Mellon University]]|accessdate=23 July 2010}}</ref>
 
=== Final variables in nested objects ===
Although it also appears to break the intent of final variables, modifying the value from another class (by getting the reference via a public getter method and changing its value) ''does'' change the value of the referenced object. For instance, according to the semantics of the final keyword, the following unit test should output "68", while in fact it outputs "82" and throws an assertion exception:
 
When final variables contain references to other objects, these objects are typically required to be immutable, too. If this is not the case, the expectation does not hold that anything reachable via the final variable is constant. For example, the following code defines a coordinate system whose origin should always be at (0, 0). The origin is implemented using a <code>java.awt.Point</code> though, and this class defines its fields as public and modifiable. This means that even when reaching the <code>origin</code> object over an access path with only final variables, that object can still be modified, as the below example code demonstrates.
 
<source lang="java">
import java.sqlawt.DatePoint;
package test;
import java.sql.Date;
public final class TestFinal {
    
    private final String name = "Andrew";
    @SuppressWarnings("deprecation")
    private final Date dob = new Date(Date.parse("07/20/1968"));
    public String getName() {
        return name;
    }
 
    final public Dateclass getDob()FinalDemo {
        return dob;
    }
}
 
static class CoordinateSystem {
package test;
private final Point origin = new Point(0, 0);
import static org.junit.Assert.*;
import java.util.Date;
import org.junit.Test;
public class TestFinalTest {
 
public Point getOrigin() { return origin; }
    @Test
}
    public void test() {
    }
 
public static void main(String[] args) {
    @Test
CoordinateSystem coordinateSystem = new CoordinateSystem();
    public void changeDate() {
 
        TestFinal testFinal = new TestFinal();
coordinateSystem.getOrigin().x = 15;
        Date initialDate = testFinal.getDob();
 
        initialDate.setYear(82);
assert coordinateSystem.getOrigin().getX() == 0;
        Date finalDate = testFinal.getDob();
}
        System.out.println(finalDate.getYear());
        assert(finalDate.getYear() == 68);
    }
}
</source>
 
The reason for this is that declaring a variable final only affectsmeans thethat reference, not the value of thethis variable, and Java always passes by value, which creates a differentwill referencepoint to the same valueobject inat theany second classtime. ThatThe theobject value ofthat the privatevariable fieldpoints canto beis changednot withoutinfluenced aby publicthat setterfinal impliesvariable thatthough. encapsulationIn isthe weak atabove bestexample, andthe shouldnorigin'ts bex countedand ony tocoordinates protectcan keybe values,freely even in combination with the final keywordmodified.
 
To prevent this undesirable situation, a common requirement is that all fields of an immutable object must be final, and that the types of these fields must be immutable themselves. This disqualifies <code>java.util.Date</code> and <code>java.awt.Point</code> and several other classes from being used in such immutable objects.
 
===Final and inner classes===