Can someone please explain output 0 in case of first constructor without this ?
Sure - this statement is a no-op:
userId = userId;
It just assigns the variable of the userId
parameter to itself. It doesn't touch the field at all. Within the method, the parameter userId
shadows the field called userId
- so you have to explicitly say that you want to refer to the field, which is what the second version does:
this.userId = userId;
I'd expect any modern IDE to highlight the no-op assignment in the first version with a warning.
(It's worth being clear about terminology, by the way - an argument is a value provided to a method; a parameter is the variable which is declared as part of the method signature. Likewise it's a field rather than a property.)
EDIT: If the parameter has a different name, e.g.
public User(int id) {
userId = id;
}
then the parameter doesn't shadow the field, and the identifier userId
still refers to the field. It's all a matter of working out what the meaning of an identifier is - in your first example, the simple name userId
refers to the parameter, which is what causes the problem.
EDIT: From section 6.4.1 of the JLS:
Some declarations may be shadowed in part of their scope by another declaration of the same name, in which case a simple name cannot be used to refer to the declared entity.
...
A declaration d of a field or formal parameter named n shadows, throughout the scope of d, the declarations of any other variables named n that are in scope at the point where d occurs.
So in this case d would be the declaration of the formal parameter userId
, and the scope of d is the constructor - so throught the constructor, the parameter shadows the field.