This question already has answers here:
What does “this” mean? [duplicate]
(6 answers)
Closed 6 years ago.
Here is my code:
class StaticBlock {
{
println("initializer block : " + message);
}
public StaticBlock(String message) {
this.message = message;
}
private String message;
}
Now the issue is that, in the initializer block
{
println("initializer block : " + message);
}
if I add the this
keyword before message
, it works, but there is an error when missing this
keyword.
And the compiler says:
StaticBlockDemo.java:34: illegal forward reference
println("initializer block : " + message);
^
1 error
Why aren't they the same?
I don't know the design rationale, but it may help to read the relevant sections of the Java language specification.
8.6. Instance Initializers
Instance initializers are permitted to refer to the current object via the keyword this
(§15.8.3), to use the keyword super
(§15.11.2, §15.12), and to use any type variables in scope.
Use of instance variables whose declarations appear textually after the use is sometimes restricted, even though these instance variables are in scope. See §8.3.2.3 for the precise rules governing forward reference to instance variables.
8.3.2.3. Restrictions on the use of Fields during Initialization
The declaration of a member needs to appear textually before it is used only if the member is an instance (respectively static
) field of a class or interface C
and all of the following conditions hold:
The usage occurs in an instance (respectively static
) variable initializer of C
or in an instance (respectively static) initializer of C
.
The usage is not on the left hand side of an assignment.
The usage is via a simple name.
C
is the innermost class or interface enclosing the usage.
Here's the example from that section of the spec trimmed down to illustrate the specific point you're asking about:
class UseBeforeDeclaration {
{
j = 200;
// ok - assignment
j = j + 1;
// error - right hand side reads before declaration
int k = j = j + 1;
// error - illegal forward reference to j
int n = j = 300;
// ok - j at left hand side of assignment
int h = j++;
// error - read before declaration
int l = this.j * 3;
// ok - not accessed via simple name
}
int j;
}
I should also note, though, that even the compiling version of your code isn't going to do what you want. If you run it:
new StaticBlock("abc");
It will print
initializer block : null
This is because initializers are executed before (most of) the constructor body. Here are the salient points from the spec:
12.5. Creation of New Class Instances
[...] the indicated constructor is processed to initialize the new object using the following procedure:
[...]
4. Execute the instance initializers and instance variable initializers for this class [...]
5. Execute the rest of the body of this constructor. [...]
if I add 'this' keyword before 'message',it works,but error when missing 'this' keyword. why they aren't the same?
this
keyword points to current instance of the class.
public StaticBlock(String message) {
this.message = message;
}
Here if you don't use this
then it will assign the value of message
local variable because scope of the local variable is more than instance in a block.
When you use the this
then it will assign the variable value of the current object variable.
One of the benefits of having classes in Java is that you can model objects as a class, and you can create multiple instances of an object (in most cases).
In order to reference information that is specific to a single object class, we can use the this
inside the object (class) code. It tells the program that you want to make use of the current
objects variables and values. By using this.message = message
, you are assigning the value of message that has been passed into the function and storing it in the object's message variable.
There are scope aspects to this, where message
has a local scope, and this.message
has the scope over the whole object. This is why when you tried to call on message in your print code: println("initializer block : " + message);
, a local variable message didn't exist within the scope of this function.
If there is clash between local variable name and instance member name, then this
keyword will compiler tell to use object variable.