Question

Is it OK to use the this keyword in a final instance variable declaration/initialization in Java?

Like this:

private final SomeClass foo = new SomeClass(this);

It worked when I tried it out. And since it is not a static variable I guess it should be referring to a particular instance. But I felt unsure if it is advisable or not so therefore I wanted to ask here.

Edit: The main class is an Android Activity class, and the SomeClass-instance needs this Activity as Context.

Was it helpful?

Solution

It is "technically valid" to do this. Indeed, this refers to a particular instance - namely, the instance that contains the instance of SomeClass.

But I would not recommend to do this in general. The exact behavior and state of the this that is passed to the constructor depends on subtle details. Consider the following example:

class SomeClass
{
    public SomeClass(DangerousSelfReference dangerousSelfReference)
    {
        System.out.println("State: ");
        System.out.println("   a: "+dangerousSelfReference.getA());
        System.out.println("   b: "+dangerousSelfReference.getB());
        System.out.println("   c: "+dangerousSelfReference.getC());
        System.out.println("   d: "+dangerousSelfReference.getD());
        System.out.println(" ref: "+dangerousSelfReference.getRef());
    }
}

public class DangerousSelfReference
{
    public static void main(String[] args)
    {
        DangerousSelfReference d = new DangerousSelfReference();
    }

    private String a;
    private String b = "b";
    private final SomeClass ref = new SomeClass(this);
    private final String c = "c";
    private String d = "d";

    DangerousSelfReference()
    {
        a = "a";
    }

    String getA()
    {
        return a;
    }
    String getB()
    {
        return b;
    }
    String getC()
    {
        return c;
    }
    String getD()
    {
        return d;
    }
    SomeClass getRef()
    {
        return ref;
    }
}

I assume that this could make a neat job interview question, because predicting the output is hard. Surprisingly, it prints

State: 
   a: null
   b: b
   c: c
   d: null
 ref: null

Notice that the final variable c is initialized, but the non-final variable d is not intialized yet. In contrast to that, the non-final variable b (that is declared before the SomeClass instance) is already intitialized.

Such subtelities are always questionable, and should be avoided if possible.

OTHER TIPS

private final SomeClass foo = new SomeClass(this);
private int bar = 42;

The SomeClass constructor will find a bar with 0.

So it is not so fine.

My first concern is : why would you need this ?

Generally, I would not recommend this as it could potentially be dangerous in more complex scenarios, where SomeClass construction depends on certain state of passed this object.

Consider, for example :

class SomeClass {
    private Foo foo;
    SomeClass(Foo foo) {
         this.foo = foo;
         // do something based on state of foo
         // such as call
         int len = foo.myString.length(); // <- this will throw NPE, because
         // foo.myString is still null as Foo() constructor wasn't called yet
    }
}

and then your Foo class:

class Foo {
    String myString = null;

    Foo() {/*constructor 1, perhaps calling init()*/
        init();
    }
    Foo(...params) {/*constructor 2*/}

    private void init() {
        // some initialization
        myString = "test String";
    }    


    // Note: this constructor is called before any of Foo's 
    // constructos are invoked
    // thus passed Foo "this" object is not initialized yet 
    // (contains defaults for all fields)
    private final SomeClass someClass = new SomeClass(this);
}

yes it is fine.

as it has nothing to do with the final keyword of the Instance variable. what you are doing is passing the enclosing class' object to the constructor of SomeClass

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top