13

I was looking at another question about final variables and noticed that you can declare final variables without initializing them (a blank final variable). Is there a reason it is desirable to do this, and when is it advantageous?

Community
  • 1
  • 1
Rob Volgman
  • 2,104
  • 3
  • 18
  • 28
  • 1
    pretty much never. blank finals do nothing. they are variables which can never have any meaningful value ever. any java compiler worth its salt will give you a warning and/or error. – Hans Z Jul 05 '12 at 13:50
  • 1
    This can be useful when you want to initialize it in the constructor (based on some constructor parameters). – sshannin Jul 05 '12 at 13:51
  • Final is final.. if you try to do final int a = 2; a = 3; it will throw an error – Matt Westlake Jul 05 '12 at 13:55
  • 2
    @sshannin declaration of a final and initialization in the constructor isn't a blank final, it's a declaration and initialization of a final variable. – Hans Z Jul 05 '12 at 13:58
  • 2
    @Hans that's exactly the definition of a blank final. – assylias Jul 05 '12 at 14:01
  • 3
    @Hans [JLS](http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.12.4): "A *blank* `final` is a `final` variable whose declaration lacks an initializer." – Marko Topolnik Jul 05 '12 at 14:06
  • Wikipedia agrees with Marko and asslias - http://en.wikipedia.org/wiki/Final_(Java)#Blank_final – Stephen C Jul 05 '12 at 14:16
  • And so does the JLS - http://docs.oracle.com/javase/specs/jls/se5.0/html/defAssign.html and http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.12.4 – Stephen C Jul 05 '12 at 14:18

9 Answers9

29

This is useful to create immutable objects:

public class Bla {
    private final Color color;

    public Bla(Color c) {this.color = c};

}

Bla is immutable (once created, it can't change because color is final). But you can still create various Blas by constructing them with various colors.

See also this question for example.

EDIT

Maybe worth adding that a "blank final" has a very specific meaning in Java, which seems to have created some confusion in the comments - cf the Java Language Specification 4.12.4:

A blank final is a final variable whose declaration lacks an initializer.

You then must assign that blank final variable in a constructor.

Community
  • 1
  • 1
assylias
  • 321,522
  • 82
  • 660
  • 783
5

The final property of class must have a value assigned before object is created. So the last point where you can assign value to them is constructor.

This is used often for immutable objects.

 public class Foo {

  private final Bar bar;

  public Foo(Bar bar) {
    this.bar = bar;
  }

  public Bar getBar() {
   return new Bar(bar);
 } 
}

What wiki says about it

Defensive copying.

2

You can do this when you do not known what the value will be prior to the instrumentation of a Object, it just needs to have a value assigned in its constructor.

This is how you make immutable objects and it is used in the builder pattern.

class Builder{
    final BuilderContext context;

    private Builder(BuilderContext context){
        this.context=context;
    }       

    public static Builder New(){
        return new Builder(new BuilderContext());
    }
John Kane
  • 4,383
  • 1
  • 24
  • 42
1

Blank final variables must be assigned "somewhere" in the constructor. A rather constructed example:

public class Test {
    final int sign;
    public Test(String upDown) {
        if (upDown.equals("up")) {
            sign = +1;
        } else {
            sign = -1;
        }
    }
}
Rainer Schwarze
  • 4,725
  • 1
  • 27
  • 49
1

One case could be when you have a field which you want to declare final, but whose assignment may throw an exception and you want to be able to take action if that happens:

class A {
  final URLConnection conn;
  A(String url) {
    try {
      this.conn = new URL(url).openConnection();
    } catch (IOException | MalformedURLException e) {
      // Maybe this isn't fatal, so just handle the Exception
      // here and move on happily
    }
  }
}
Gustav Barkefors
  • 5,016
  • 26
  • 30
1

Use a blank final variable inside a method to show that all code paths which use the variable assign that variable exactly once (or throw an exception). Java compilers will guarantee that a blank final variable is assigned before it is used.

Example code inside some method:

  final Foo foo;
  if (condition1()) {
    foo = makeFoo(1);
  } else if (condition2()) {
    throw new BarException();
  } else {
    foo = makeFoo(-1);
  }
  ...
  blahBlahBlah(foo);

Using blank final variables tells the next reader of the code that the compiler guarantees that someone assigned foo before calling blahBlahBlah(foo).

The question asks about "blank final variables". Discussion of "blank final fields" is a different discussion, and interesting in its own right.

0

noticed that you can declare final variables without initializing them

You have to initialize it later (for example in the constructor) so it wont stay empty.

Adam
  • 15,537
  • 2
  • 42
  • 63
Pshemo
  • 122,468
  • 25
  • 185
  • 269
0

From Wikipedia

The blank final, which was introduced in Java 1.1, is a final variable whose declaration lacks an initializer. A blank final can only be assigned once and must be unassigned when an assignment occurs. In order to do this, a Java compiler runs a flow analysis to ensure that, for every assignment to a blank final variable, the variable is definitely unassigned before the assignment; otherwise a compile-time error occurs.

In general, a Java compiler will ensure that the blank final is not used until it is assigned a value and that once assigned a value, the now final variable cannot be reassigned another value.

marty bourque
  • 734
  • 4
  • 7
  • 20
0

I find them very useful for methods that derive a state. It provides a clean execution path and makes sure the state variable is assigned once and only once. For example:

public boolean isEdible() {
    final boolean edible;

    if (vegetable) {
        edible = true;
    } else if (animal) {
        if (vegetarian) {
            edible = false;
        } else {
            edible = true;
        } 
    }
    System.out.println("Is edible: " + edible);
    return edible;
}
Dustin
  • 2,064
  • 1
  • 16
  • 12