Search code examples
javaandroidfinal

Is it ok to use 'this' in final instance variable declaration?


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.


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.