Reputation: 71
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.
Upvotes: 0
Views: 138
Reputation: 9450
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);
}
Upvotes: 1
Reputation: 54659
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.
Upvotes: 4
Reputation: 109597
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.
Upvotes: 3
Reputation: 2081
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
Upvotes: -1